diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/accepted.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/active.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/object_safety.rs | 44 |
10 files changed, 95 insertions, 37 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0017a28cf1b..0b033e9384c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -461,7 +461,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { gate_feature_post!( &self, - half_open_range_patterns, + half_open_range_patterns_in_slices, pat.span, "`X..` patterns in slices are experimental" ); @@ -589,7 +589,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(generators, "yield syntax is experimental"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); - gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); + gate_all!( + half_open_range_patterns_in_slices, + "half-open range patterns in slices are unstable" + ); gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); gate_all!(associated_const_equality, "associated const equality is incomplete"); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 8efb7ccc1c7..ca12659695f 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -169,6 +169,8 @@ declare_features! ( (accepted, global_allocator, "1.28.0", Some(27389), None), // FIXME: explain `globs`. (accepted, globs, "1.0.0", None, None), + /// Allows using `..=X` as a pattern. + (accepted, half_open_range_patterns, "CURRENT_RUSTC_VERSION", Some(67264), None), /// Allows using the `u128` and `i128` types. (accepted, i128_type, "1.26.0", Some(35118), None), /// Allows the use of `if let` expressions. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 71ad54291b2..48c40eae662 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -414,6 +414,8 @@ declare_features! ( (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. (active, half_open_range_patterns, "1.41.0", Some(67264), None), + /// Allows using `..=X` as a patterns in slices. + (active, half_open_range_patterns_in_slices, "CURRENT_RUSTC_VERSION", Some(67264), None), /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), /// Allows using imported `main` function diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index a180706e1cf..8d9a0388e21 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -44,7 +44,7 @@ #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] -#![feature(half_open_range_patterns)] +#![cfg_attr(bootstrap, feature(half_open_range_patterns))] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] #![feature(trusted_step)] diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 4d0a8b05eb0..fa75670b2ed 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,7 +1,9 @@ use super::{ForceCollect, Parser, TrailingToken}; use rustc_ast::token; -use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause}; +use rustc_ast::{ + self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, +}; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::kw; @@ -31,13 +33,43 @@ impl<'a> Parser<'a> { let mut colon_span = None; let bounds = if self.eat(&token::Colon) { colon_span = Some(self.prev_token.span); + // recover from `impl Trait` in type param bound + if self.token.is_keyword(kw::Impl) { + let impl_span = self.token.span; + let snapshot = self.create_snapshot_for_diagnostic(); + match self.parse_ty() { + Ok(p) => { + if let TyKind::ImplTrait(_, bounds) = &(*p).kind { + let span = impl_span.to(self.token.span.shrink_to_lo()); + let mut err = self.struct_span_err( + span, + "expected trait bound, found `impl Trait` type", + ); + err.span_label(span, "not a trait"); + if let [bound, ..] = &bounds[..] { + err.span_suggestion_verbose( + impl_span.until(bound.span()), + "use the trait bounds directly", + String::new(), + Applicability::MachineApplicable, + ); + } + err.emit(); + return Err(err); + } + } + Err(err) => { + err.cancel(); + } + } + self.restore_snapshot(snapshot); + } self.parse_generic_bounds(colon_span)? } else { Vec::new() }; let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; - Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 0250b518243..56efec422d6 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -777,7 +777,6 @@ impl<'a> Parser<'a> { /// expression syntax `...expr` for splatting in expressions. fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> { let end = self.parse_pat_range_end()?; - self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_token.span)); if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node { *syn = RangeSyntax::DotDotEq; self.struct_span_err(re.span, "range-to patterns with `...` are not allowed") diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 8fa6160d436..c18d5d06d64 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1333,12 +1333,41 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { - rustc_session::parse::feature_err( + let mut diag = rustc_session::parse::feature_err( &self.tcx.sess.parse_sess, sym::anonymous_lifetime_in_impl_trait, lifetime_ref.span, "anonymous lifetimes in `impl Trait` are unstable", - ).emit(); + ); + + match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) { + Some(generics) => { + + let new_param_sugg_tuple; + + new_param_sugg_tuple = match generics.span_for_param_suggestion() { + Some(_) => { + Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned())) + }, + None => Some((generics.span, "<'a>".to_owned())) + }; + + let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())]; + + if let Some(new_tuple) = new_param_sugg_tuple{ + multi_sugg_vec.push(new_tuple); + } + + diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); + diag.multipart_suggestion("consider introducing a named lifetime parameter", + multi_sugg_vec, + rustc_errors::Applicability::MaybeIncorrect); + + }, + None => { } + } + + diag.emit(); return; } scope = s; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f8df4169715..91eef647713 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -298,7 +298,11 @@ impl From<PathBuf> for FileName { #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] pub enum FileNameDisplayPreference { + /// Display the path after the application of rewrite rules provided via `--remap-path-prefix`. + /// This is appropriate for paths that get embedded into files produced by the compiler. Remapped, + /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`. + /// This is appropriate for use in user-facing output (such as diagnostics). Local, } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8cb7d147d02..fe4fd33bdba 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -785,6 +785,7 @@ symbols! { globs, gt, half_open_range_patterns, + half_open_range_patterns_in_slices, hash, hexagon_target_feature, hidden, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 52ee5e6ea93..1afa04007b8 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -8,7 +8,7 @@ //! - not reference the erased type `Self` except for in this receiver; //! - not have generic type parameters. -use super::elaborate_predicates; +use super::{elaborate_predicates, elaborate_trait_ref}; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; @@ -567,51 +567,37 @@ fn receiver_for_self_ty<'tcx>( /// Creates the object type for the current trait. For example, /// if the current trait is `Deref`, then this will be /// `dyn Deref<Target = Self::Target> + 'static`. +#[instrument(level = "trace", skip(tcx), ret)] fn object_ty_for_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, lifetime: ty::Region<'tcx>, ) -> Ty<'tcx> { - debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id); - let trait_ref = ty::TraitRef::identity(tcx, trait_def_id); + debug!(?trait_ref); let trait_predicate = trait_ref.map_bound(|trait_ref| { ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)) }); + debug!(?trait_predicate); - let mut associated_types = traits::supertraits(tcx, trait_ref) - .flat_map(|super_trait_ref| { - tcx.associated_items(super_trait_ref.def_id()) - .in_definition_order() - .map(move |item| (super_trait_ref, item)) - }) - .filter(|(_, item)| item.kind == ty::AssocKind::Type) - .collect::<Vec<_>>(); - - // existential predicates need to be in a specific order - associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id)); - - let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| { - // We *can* get bound lifetimes here in cases like - // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`. - super_trait_ref.map_bound(|super_trait_ref| { + let elaborated_predicates = elaborate_trait_ref(tcx, trait_ref).filter_map(|obligation| { + debug!(?obligation); + let pred = obligation.predicate.to_opt_poly_projection_pred()?; + Some(pred.map_bound(|p| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { - term: tcx.mk_projection(item.def_id, super_trait_ref.substs).into(), - item_def_id: item.def_id, - substs: super_trait_ref.substs, + item_def_id: p.projection_ty.item_def_id, + substs: p.projection_ty.substs, + term: p.term, }) - }) + })) }); let existential_predicates = tcx - .mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates)); - - let object_ty = tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn); - - debug!("object_ty_for_trait: object_ty=`{}`", object_ty); + .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates)); + debug!(?existential_predicates); - object_ty + tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn) } /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a |
