Skip to content

Commit 1ef7ddf

Browse files
committed
typeck: disallow impl Trait outside of return types of functions and impl methods.
1 parent ef11d4e commit 1ef7ddf

File tree

5 files changed

+174
-43
lines changed

5 files changed

+174
-43
lines changed

src/librustc/middle/resolve_lifetime.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
832832
constrained_by_input.visit_ty(&arg.ty);
833833
}
834834

835-
let mut appears_in_output = AllCollector { regions: FnvHashSet() };
835+
let mut appears_in_output = AllCollector {
836+
regions: FnvHashSet(),
837+
impl_trait: false
838+
};
836839
intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
837840

838841
debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
@@ -842,7 +845,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
842845
//
843846
// Subtle point: because we disallow nested bindings, we can just
844847
// ignore binders here and scrape up all names we see.
845-
let mut appears_in_where_clause = AllCollector { regions: FnvHashSet() };
848+
let mut appears_in_where_clause = AllCollector {
849+
regions: FnvHashSet(),
850+
impl_trait: false
851+
};
846852
for ty_param in generics.ty_params.iter() {
847853
walk_list!(&mut appears_in_where_clause,
848854
visit_ty_param_bound,
@@ -864,12 +870,16 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
864870
// Late bound regions are those that:
865871
// - appear in the inputs
866872
// - do not appear in the where-clauses
873+
// - are not implicitly captured by `impl Trait`
867874
for lifetime in &generics.lifetimes {
868875
let name = lifetime.lifetime.name;
869876

870877
// appears in the where clauses? early-bound.
871878
if appears_in_where_clause.regions.contains(&name) { continue; }
872879

880+
// any `impl Trait` in the return type? early-bound.
881+
if appears_in_output.impl_trait { continue; }
882+
873883
// does not appear in the inputs, but appears in the return
874884
// type? eventually this will be early-bound, but for now we
875885
// just mark it so we can issue warnings.
@@ -932,12 +942,20 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
932942

933943
struct AllCollector {
934944
regions: FnvHashSet<ast::Name>,
945+
impl_trait: bool
935946
}
936947

937948
impl<'v> Visitor<'v> for AllCollector {
938949
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
939950
self.regions.insert(lifetime_ref.name);
940951
}
952+
953+
fn visit_ty(&mut self, ty: &hir::Ty) {
954+
if let hir::TyImplTrait(_) = ty.node {
955+
self.impl_trait = true;
956+
}
957+
intravisit::walk_ty(self, ty);
958+
}
941959
}
942960
}
943961

src/librustc_typeck/astconv.rs

+49-25
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use require_c_abi_if_variadic;
6565
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
6666
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
6767
ElisionFailureInfo, ElidedLifetime};
68+
use rscope::{AnonTypeScope, MaybeWithAnonTypes};
6869
use util::common::{ErrorReported, FN_OUTPUT_NAME};
6970
use util::nodemap::{NodeMap, FnvHashSet};
7071

@@ -635,20 +636,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
635636

636637
fn convert_ty_with_lifetime_elision(&self,
637638
elided_lifetime: ElidedLifetime,
638-
ty: &hir::Ty)
639+
ty: &hir::Ty,
640+
anon_scope: Option<AnonTypeScope>)
639641
-> Ty<'tcx>
640642
{
641643
match elided_lifetime {
642644
Ok(implied_output_region) => {
643645
let rb = ElidableRscope::new(implied_output_region);
644-
self.ast_ty_to_ty(&rb, ty)
646+
self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
645647
}
646648
Err(param_lifetimes) => {
647649
// All regions must be explicitly specified in the output
648650
// if the lifetime elision rules do not apply. This saves
649651
// the user from potentially-confusing errors.
650652
let rb = UnelidableRscope::new(param_lifetimes);
651-
self.ast_ty_to_ty(&rb, ty)
653+
self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
652654
}
653655
}
654656
}
@@ -665,7 +667,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
665667
let region_substs =
666668
self.create_region_substs(rscope, span, decl_generics, Vec::new());
667669

668-
let binding_rscope = BindingRscope::new();
670+
let anon_scope = rscope.anon_type_scope();
671+
let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
669672
let inputs =
670673
data.inputs.iter()
671674
.map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
@@ -679,7 +682,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
679682

680683
let (output, output_span) = match data.output {
681684
Some(ref output_ty) => {
682-
(self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
685+
(self.convert_ty_with_lifetime_elision(implied_output_region,
686+
&output_ty,
687+
anon_scope),
683688
output_ty.span)
684689
}
685690
None => {
@@ -1703,7 +1708,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
17031708
}
17041709
hir::TyBareFn(ref bf) => {
17051710
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
1706-
let bare_fn_ty = self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl);
1711+
let anon_scope = rscope.anon_type_scope();
1712+
let (bare_fn_ty, _) =
1713+
self.ty_of_method_or_bare_fn(bf.unsafety,
1714+
bf.abi,
1715+
None,
1716+
&bf.decl,
1717+
anon_scope,
1718+
anon_scope);
17071719

17081720
// Find any late-bound regions declared in return type that do
17091721
// not appear in the arguments. These are not wellformed.
@@ -1751,10 +1763,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
17511763

17521764
// Create the anonymized type.
17531765
let def_id = tcx.map.local_def_id(ast_ty.id);
1754-
let substs = tcx.mk_substs(Substs::empty());
1766+
let substs = if let Some(anon_scope) = rscope.anon_type_scope() {
1767+
anon_scope.fresh_substs(tcx)
1768+
} else {
1769+
span_err!(tcx.sess, ast_ty.span, E0562,
1770+
"`impl Trait` not allowed outside of function \
1771+
and inherent method return types");
1772+
tcx.mk_substs(Substs::empty())
1773+
};
17551774
let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
17561775

1757-
// Collect the bounds, i.e. the `Trait` in `impl Trait`.
1776+
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
17581777
let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span);
17591778
let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap();
17601779
let predicates = ty::GenericPredicates {
@@ -1828,36 +1847,40 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18281847

18291848
pub fn ty_of_method(&self,
18301849
sig: &hir::MethodSig,
1831-
untransformed_self_ty: Ty<'tcx>)
1850+
untransformed_self_ty: Ty<'tcx>,
1851+
anon_scope: Option<AnonTypeScope>)
18321852
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
1833-
let (bare_fn_ty, optional_explicit_self_category) =
1834-
self.ty_of_method_or_bare_fn(sig.unsafety,
1835-
sig.abi,
1836-
Some(untransformed_self_ty),
1837-
&sig.decl);
1838-
(bare_fn_ty, optional_explicit_self_category)
1853+
self.ty_of_method_or_bare_fn(sig.unsafety,
1854+
sig.abi,
1855+
Some(untransformed_self_ty),
1856+
&sig.decl,
1857+
None,
1858+
anon_scope)
18391859
}
18401860

18411861
pub fn ty_of_bare_fn(&self,
18421862
unsafety: hir::Unsafety,
18431863
abi: abi::Abi,
1844-
decl: &hir::FnDecl)
1864+
decl: &hir::FnDecl,
1865+
anon_scope: Option<AnonTypeScope>)
18451866
-> &'tcx ty::BareFnTy<'tcx> {
1846-
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0
1867+
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
18471868
}
18481869

1849-
fn ty_of_method_or_bare_fn<'a>(&self,
1850-
unsafety: hir::Unsafety,
1851-
abi: abi::Abi,
1852-
opt_untransformed_self_ty: Option<Ty<'tcx>>,
1853-
decl: &hir::FnDecl)
1854-
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
1870+
fn ty_of_method_or_bare_fn(&self,
1871+
unsafety: hir::Unsafety,
1872+
abi: abi::Abi,
1873+
opt_untransformed_self_ty: Option<Ty<'tcx>>,
1874+
decl: &hir::FnDecl,
1875+
arg_anon_scope: Option<AnonTypeScope>,
1876+
ret_anon_scope: Option<AnonTypeScope>)
1877+
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
18551878
{
18561879
debug!("ty_of_method_or_bare_fn");
18571880

18581881
// New region names that appear inside of the arguments of the function
18591882
// declaration are bound to that function type.
1860-
let rb = rscope::BindingRscope::new();
1883+
let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
18611884

18621885
// `implied_output_region` is the region that will be assumed for any
18631886
// region parameters in the return type. In accordance with the rules for
@@ -1895,7 +1918,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18951918
let output_ty = match decl.output {
18961919
hir::Return(ref output) =>
18971920
ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
1898-
&output)),
1921+
&output,
1922+
ret_anon_scope)),
18991923
hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
19001924
hir::NoReturn(..) => ty::FnDiverging
19011925
};

src/librustc_typeck/collect.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -564,13 +564,17 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
564564
let ty_generic_predicates =
565565
ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
566566

567-
let (fty, explicit_self_category) =
567+
let (fty, explicit_self_category) = {
568+
let anon_scope = match container {
569+
ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)),
570+
TraitContainer(_) => None
571+
};
568572
AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
569-
sig,
570-
untransformed_rcvr_ty);
573+
sig, untransformed_rcvr_ty, anon_scope)
574+
};
571575

572576
let def_id = ccx.tcx.map.local_def_id(id);
573-
let substs = mk_item_substs(ccx, &ty_generics);
577+
let substs = mk_item_substs(ccx.tcx, &ty_generics);
574578

575579
let ty_method = ty::Method::new(name,
576580
ty_generics,
@@ -961,7 +965,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
961965
.map(|field| field.unsubst_ty())
962966
.collect();
963967
let def_id = tcx.map.local_def_id(ctor_id);
964-
let substs = mk_item_substs(ccx, &scheme.generics);
968+
let substs = mk_item_substs(tcx, &scheme.generics);
965969
tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
966970
unsafety: hir::Unsafety::Normal,
967971
abi: abi::Abi::Rust,
@@ -1460,9 +1464,10 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
14601464
}
14611465
hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
14621466
let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1463-
let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
1467+
let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
1468+
Some(AnonTypeScope::new(&ty_generics)));
14641469
let def_id = ccx.tcx.map.local_def_id(it.id);
1465-
let substs = mk_item_substs(ccx, &ty_generics);
1470+
let substs = mk_item_substs(tcx, &ty_generics);
14661471
let ty = tcx.mk_fn_def(def_id, substs, tofd);
14671472
ty::TypeScheme { ty: ty, generics: ty_generics }
14681473
}
@@ -1474,14 +1479,14 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
14741479
hir::ItemEnum(ref ei, ref generics) => {
14751480
let def = convert_enum_def(ccx, it, ei);
14761481
let ty_generics = ty_generics_for_type(ccx, generics);
1477-
let substs = mk_item_substs(ccx, &ty_generics);
1482+
let substs = mk_item_substs(tcx, &ty_generics);
14781483
let t = tcx.mk_enum(def, substs);
14791484
ty::TypeScheme { ty: t, generics: ty_generics }
14801485
}
14811486
hir::ItemStruct(ref si, ref generics) => {
14821487
let def = convert_struct_def(ccx, it, si);
14831488
let ty_generics = ty_generics_for_type(ccx, generics);
1484-
let substs = mk_item_substs(ccx, &ty_generics);
1489+
let substs = mk_item_substs(tcx, &ty_generics);
14851490
let t = tcx.mk_struct(def, substs);
14861491
ty::TypeScheme { ty: t, generics: ty_generics }
14871492
}
@@ -2194,7 +2199,7 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
21942199
}
21952200
}
21962201

2197-
let substs = mk_item_substs(ccx, &ty_generics);
2202+
let substs = mk_item_substs(ccx.tcx, &ty_generics);
21982203
let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
21992204
abi: abi,
22002205
unsafety: hir::Unsafety::Unsafe,
@@ -2209,19 +2214,19 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
22092214
}
22102215
}
22112216

2212-
fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2213-
ty_generics: &ty::Generics<'tcx>)
2214-
-> &'tcx Substs<'tcx>
2217+
pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
2218+
ty_generics: &ty::Generics)
2219+
-> &'tcx Substs<'tcx>
22152220
{
22162221
let types =
22172222
ty_generics.types.map(
2218-
|def| ccx.tcx.mk_param_from_def(def));
2223+
|def| tcx.mk_param_from_def(def));
22192224

22202225
let regions =
22212226
ty_generics.regions.map(
22222227
|def| def.to_early_bound_region());
22232228

2224-
ccx.tcx.mk_substs(Substs::new(types, regions))
2229+
tcx.mk_substs(Substs::new(types, regions))
22252230
}
22262231

22272232
/// Checks that all the type parameters on an impl

src/librustc_typeck/diagnostics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4084,4 +4084,6 @@ register_diagnostics! {
40844084
E0513, // no type for local variable ..
40854085
E0521, // redundant default implementations of trait
40864086
E0533, // `{}` does not name a unit variant, unit struct or a constant
4087+
E0562, // `impl Trait` not allowed outside of function
4088+
// and inherent method return types
40874089
}

0 commit comments

Comments
 (0)