diff options
| author | Alexander Regueiro <alexreg@me.com> | 2018-10-26 23:13:12 +0100 |
|---|---|---|
| committer | Alexander Regueiro <alexreg@me.com> | 2018-11-03 04:09:34 +0000 |
| commit | 4bdc3d833af1229420fce37b245d5cccd1d7cc3f (patch) | |
| tree | 3efa920f528793a265744570e61ccb50b477db3d /src | |
| parent | a8fcfcef3087e9770fa016c5776ce5bf25558ed7 (diff) | |
| download | rust-4bdc3d833af1229420fce37b245d5cccd1d7cc3f.tar.gz rust-4bdc3d833af1229420fce37b245d5cccd1d7cc3f.zip | |
Extended elaboration for trait aliases to include arbitrary bounds.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/traits/select.rs | 10 | ||||
| -rw-r--r-- | src/librustc/traits/util.rs | 2 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 12 | ||||
| -rw-r--r-- | src/librustc/ty/util.rs | 2 | ||||
| -rw-r--r-- | src/librustc_passes/ast_validation.rs | 19 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 10 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 40 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-alias-fail1.rs | 7 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-alias-fail1.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-alias-fail2.rs | 2 |
11 files changed, 57 insertions, 59 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6d9e8d2fbe0..4b41831afbb 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1635,7 +1635,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ambiguous: false, }; - self.assemble_candidates_for_alias(obligation, &mut candidates)?; + self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?; // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. @@ -2255,14 +2255,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn assemble_candidates_for_alias( + fn assemble_candidates_for_trait_alias( &mut self, obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // OK to skip binder here because the tests we do below do not involve bound regions let self_ty = *obligation.self_ty().skip_binder(); - debug!("assemble_candidates_for_alias(self_ty={:?})", self_ty); + debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty); let def_id = obligation.predicate.def_id(); @@ -2907,7 +2907,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.vtable_auto_impl(obligation, trait_def_id, types) } - /// See `confirm_auto_impl_candidate` + /// See `confirm_auto_impl_candidate`. fn vtable_auto_impl( &mut self, obligation: &TraitObligation<'tcx>, @@ -2964,7 +2964,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // this time not in a probe. self.in_snapshot(|this, snapshot| { let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot); - debug!("confirm_impl_candidate substs={:?}", substs); + debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); this.vtable_impl( impl_def_id, diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 940cf736012..74f8d67ce04 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -333,7 +333,7 @@ impl<I> FilterToTraits<I> { } } -impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> { +impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> { type Item = ty::PolyTraitRef<'tcx>; fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f3ae15e3b3c..3d9ec7245f9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1051,24 +1051,24 @@ pub enum Predicate<'tcx> { /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), - /// where 'a : 'b + /// where `'a : 'b` RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), - /// where T : 'a + /// where `T : 'a` TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), - /// where <T as TraitRef>::Name == X, approximately. - /// See `ProjectionPredicate` struct for details. + /// where `<T as TraitRef>::Name == X`, approximately. + /// See the `ProjectionPredicate` struct for details. Projection(PolyProjectionPredicate<'tcx>), - /// no syntax: T WF + /// no syntax: `T` well-formed WellFormed(Ty<'tcx>), /// trait must be object-safe ObjectSafe(DefId), /// No direct syntax. May be thought of as `where T : FnFoo<...>` - /// for some substitutions `...` and T being a closure type. + /// for some substitutions `...` and `T` being a closure type. /// Satisfied (or refuted) once we know the closure's kind. ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind), diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 00a1bfaacd7..a6997260784 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -527,7 +527,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr } - /// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`). + /// True if `def_id` refers to a trait (i.e., `trait Foo { ... }`). pub fn is_trait(self, def_id: DefId) -> bool { if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data { true diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 0e9596244cd..61861da62f7 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -403,25 +403,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - ItemKind::TraitAlias(Generics { ref params, .. }, ..) => { - for param in params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { - if !param.bounds.is_empty() { - self.err_handler() - .span_err(param.ident.span, "type parameters on the left \ - side of a trait alias cannot be bounded"); - } - if !default.is_none() { - self.err_handler() - .span_err(param.ident.span, "type parameters on the left \ - side of a trait alias cannot have defaults"); - } - } - } - } - } ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e8a502d6ca8..9556be6ebfc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -544,7 +544,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } /// Given the type/region arguments provided to some path (along with - /// an implicit Self, if this is a trait reference) returns the complete + /// an implicit `Self`, if this is a trait reference) returns the complete /// set of substitutions. This may involve applying defaulted type parameters. /// /// Note that the type listing given here is *exactly* what the user provided. @@ -721,7 +721,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { { let trait_def_id = self.trait_def_id(trait_ref); - debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); + debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); @@ -738,11 +738,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let predicate: Result<_, ErrorReported> = self.ast_type_binding_to_poly_projection_predicate( trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings); - // ok to ignore Err() because ErrorReported (see above) + // ok to ignore Err because ErrorReported (see above) Some((predicate.ok()?, binding.span)) })); - debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}", + debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}", trait_ref, poly_projections, poly_trait_ref); poly_trait_ref } @@ -1020,7 +1020,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { return tcx.types.err; } - // use a btreeset to keep output in a more consistent order + // use a BTreeSet to keep output in a more consistent order let mut associated_types = BTreeSet::default(); for tr in traits::supertraits(tcx, principal) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a8b24019af0..21a1abd97a5 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -245,8 +245,8 @@ fn type_param_predicates<'a, 'tcx>( use rustc::hir::*; // In the AST, bounds can derive from two places. Either - // written inline like `<T:Foo>` or in a where clause like - // `where T:Foo`. + // written inline like `<T : Foo>` or in a where clause like + // `where T : Foo`. let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); let param_owner = tcx.hir.ty_param_owner(param_id); @@ -317,12 +317,12 @@ fn type_param_predicates<'a, 'tcx>( let icx = ItemCtxt::new(tcx, item_def_id); result .predicates - .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); + .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, true)); result } impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { - /// Find bounds from hir::Generics. This requires scanning through the + /// Find bounds from `hir::Generics`. This requires scanning through the /// AST. We do this to avoid having to convert *all* the bounds, which /// would create artificial cycles. Instead we can only convert the /// bounds for a type parameter `X` if `X::Foo` is used. @@ -331,6 +331,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { ast_generics: &hir::Generics, param_id: ast::NodeId, ty: Ty<'tcx>, + only_self_bounds: bool, ) -> Vec<(ty::Predicate<'tcx>, Span)> { let from_ty_params = ast_generics .params @@ -350,9 +351,21 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), _ => None, }) - .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id)) - .flat_map(|bp| bp.bounds.iter()) - .flat_map(|b| predicates_from_bound(self, ty, b)); + .flat_map(|bp| { + let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) { + Some(ty) + } else { + if only_self_bounds { + None + } else { + Some(self.to_ty(&bp.bounded_ty)) + } + }; + bp.bounds.iter().filter_map(move |b| { + if let Some(bt) = bt { Some((bt, b)) } else { None } + }) + }) + .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); from_ty_params.chain(from_where_clauses).collect() } @@ -690,7 +703,7 @@ fn super_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); - // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. + // Convert the bounds that follow the colon, e.g. `Bar + Zed` in `trait Foo : Bar + Zed`. let self_param_ty = tcx.mk_self_type(); let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); @@ -698,7 +711,9 @@ fn super_predicates_of<'a, 'tcx>( // Convert any explicit superbounds in the where clause, // e.g. `trait Foo where Self : Bar`: - let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty); + let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id); + let superbounds2 = icx.type_parameter_bounds_in_generics( + generics, item.id, self_param_ty, !is_trait_alias); // Combine the two lists to form the complete set of superbounds: let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect(); @@ -706,6 +721,7 @@ fn super_predicates_of<'a, 'tcx>( // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. for &(pred, span) in &superbounds { + debug!("superbound: {:?}", pred); if let ty::Predicate::Trait(bound) = pred { tcx.at(span).super_predicates_of(bound.def_id()); } @@ -2007,10 +2023,10 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>( } } -/// Converts a specific GenericBound from the AST into a set of +/// Converts a specific `GenericBound` from the AST into a set of /// predicates that apply to the self-type. A vector is returned -/// because this can be anywhere from 0 predicates (`T:?Sized` adds no -/// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar` +/// because this can be anywhere from zero predicates (`T : ?Sized` adds no +/// predicates) to one (`T : Foo`) to many (`T : Bar<X=i32>` adds `T : Bar` /// and `<T as Bar>::X == i32`). fn predicates_from_bound<'tcx>( astconv: &dyn AstConv<'tcx, 'tcx>, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6018744215b..d3416d6923c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1295,7 +1295,7 @@ impl<'a> Parser<'a> { self.check_keyword(keywords::Extern) && self.is_extern_non_path() } - /// parse a TyKind::BareFn type: + /// parse a `TyKind::BareFn` type: fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> { /* @@ -5779,7 +5779,7 @@ impl<'a> Parser<'a> { ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? { - // Method macro. + // method macro Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) } else { @@ -6792,11 +6792,11 @@ impl<'a> Parser<'a> { Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) } - /// Parse type Foo = Bar; + /// Parse `type Foo = Bar;` /// or - /// existential type Foo: Bar; + /// `existential type Foo: Bar;` /// or - /// return None without modifying the parser state + /// `return None` without modifying the parser state fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> { // This parses the grammar: // Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";" diff --git a/src/test/ui/traits/trait-alias-fail1.rs b/src/test/ui/traits/trait-alias-fail1.rs index 135fdf93c29..25c850db6ce 100644 --- a/src/test/ui/traits/trait-alias-fail1.rs +++ b/src/test/ui/traits/trait-alias-fail1.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-trait_alias +#![feature(trait_alias)] trait CloneDefault<T> = Default where T: Clone; trait BoundedAlias<T: Clone = ()> = Default; -trait A<T: Send> {} -trait B<T> = A<T>; // FIXME: parameter T should need a bound here, or semantics should be changed +trait Foo {} +trait A<T: Foo> {} +trait B<T> = A<T>; // T cannot be unbounded impl CloneDefault for () {} diff --git a/src/test/ui/traits/trait-alias-fail1.stderr b/src/test/ui/traits/trait-alias-fail1.stderr index 565409be782..447f4b1b9de 100644 --- a/src/test/ui/traits/trait-alias-fail1.stderr +++ b/src/test/ui/traits/trait-alias-fail1.stderr @@ -35,7 +35,7 @@ LL | trait BoundedAlias<T: Clone = ()> = Default; error[E0658]: trait aliases are experimental (see issue #41517) --> $DIR/trait-alias-fail1.rs:17:1 | -LL | trait B<T> = A<T>; // FIXME: this should not work... or should it? +LL | trait B<T> = A<T>; // FIXME: parameter T should need a bound here, or semantics should be changed | ^^^^^^^^^^^^^^^^^^ | = help: add #![feature(trait_alias)] to the crate attributes to enable diff --git a/src/test/ui/traits/trait-alias-fail2.rs b/src/test/ui/traits/trait-alias-fail2.rs index 3d32cf6d29b..3adcd8436d8 100644 --- a/src/test/ui/traits/trait-alias-fail2.rs +++ b/src/test/ui/traits/trait-alias-fail2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-trait_alias +#![feature(trait_alias)] trait EqAlias = Eq; trait IteratorAlias = Iterator; |
