diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 21077c312bdc8..7bfd50afe6ed9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1574,6 +1574,16 @@ impl GenBlockKind { pub struct QSelf { pub ty: P, + /// The constness of the trait (under feature `const_trait_impl`). + /// + /// * `::AssocTy`: `BoundConstness::Never` + /// * `::AssocTy`: `BoundConstness::Always` + /// * `::AssocTy`: `BoundConstness::Maybe` + // FIXME(effects): This is the most convenient place to put this information but + // it doesn't make much sense from a conceptual viewpoint since it doesn't have + // much to do with the self type. + pub constness: BoundConstness, + /// The span of `a::b::Trait` in a path like ` as /// a::b::Trait>::AssociatedItem`; in the case where `position == /// 0`, this is an empty span. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 450555d0cb56d..eb69c0baf16a8 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -559,7 +559,7 @@ pub fn noop_visit_path(Path { segments, span, tokens }: &mut Path pub fn noop_visit_qself(qself: &mut Option>, vis: &mut T) { visit_opt(qself, |qself| { - let QSelf { ty, path_span, position: _ } = &mut **qself; + let QSelf { ty, constness: _, path_span, position: _ } = &mut **qself; vis.visit_ty(ty); vis.visit_span(path_span); }) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a3ff02f5f6954..b921b8d5ca481 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -200,36 +200,35 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Const(ty, generics, body_id) } ItemKind::Fn(box Fn { - sig: FnSig { decl, header, span: fn_sig_span }, + sig: FnSig { decl: ast_decl, header, span: fn_sig_span }, generics, body, .. }) => { self.with_new_scopes(ident.span, |this| { - // Note: we don't need to change the return type from `T` to - // `impl Future` here because lower_body - // only cares about the input argument patterns in the function - // declaration (decl), not the return types. - let coroutine_kind = header.coroutine_kind; - let body_id = this.lower_maybe_coroutine_body( - span, - hir_id, - decl, - coroutine_kind, - body.as_deref(), - ); - + // We lower the generics before we lower the body since the body can bind the host + // effect param via qualified paths of the form `::AssocType`. let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, header.constness, id, &itctx, |this| { this.lower_fn_decl( - decl, + ast_decl, id, *fn_sig_span, FnDeclKind::Fn, - coroutine_kind, + header.coroutine_kind, ) }); + // Note: We don't need to change the return type from `T` to `impl Future` + // here because `lower_body` only cares about the input argument patterns in the function + // declaration `decl`, not the return types. + let body_id = this.lower_maybe_coroutine_body( + span, + hir_id, + ast_decl, + header.coroutine_kind, + body.as_deref(), + ); let sig = hir::FnSig { decl, header: this.lower_fn_header(*header), @@ -600,9 +599,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.host_param_id = generics .params .iter() - .find(|param| { - matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }) - }) + .rev() + .find(|param| param.is_host_effect()) .map(|param| param.def_id); } @@ -1461,9 +1459,26 @@ impl<'hir> LoweringContext<'_, 'hir> { .map(|predicate| self.lower_where_predicate(predicate)), ); - let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self - .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics) - .collect(); + let mut params = SmallVec::<[hir::GenericParam<'hir>; 4]>::new(); + + let mut encountered_defaulted_param = false; + for param in &generics.params { + let param = self.lower_generic_param(param, hir::GenericParamSource::Generics); + + // FIXME(fmease): Add explainer. + if !encountered_defaulted_param && param.has_default() { + if let Some((span, hir_id, def_id)) = host_param_parts { + params.push(self.make_host_effect_param(span, hir_id, def_id)); + } + encountered_defaulted_param = true; + } + + params.push(param); + } + + if !encountered_defaulted_param && let Some((span, hir_id, def_id)) = host_param_parts { + params.push(self.make_host_effect_param(span, hir_id, def_id)); + } // Introduce extra lifetimes if late resolution tells us to. let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id); @@ -1487,69 +1502,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds); predicates.extend(impl_trait_bounds.into_iter()); - if let Some((span, hir_id, def_id)) = host_param_parts { - let const_node_id = self.next_node_id(); - let anon_const = - self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); - - let const_id = self.next_id(); - let const_expr_id = self.next_id(); - let bool_id = self.next_id(); - - self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); - - let const_body = self.lower_body(|this| { - ( - &[], - hir::Expr { - hir_id: const_expr_id, - kind: hir::ExprKind::Lit( - this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }), - ), - span, - }, - ) - }); - - let param = hir::GenericParam { - def_id, - hir_id, - name: hir::ParamName::Plain(Ident { name: sym::host, span }), - span, - kind: hir::GenericParamKind::Const { - ty: self.arena.alloc(self.ty( - span, - hir::TyKind::Path(hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - res: Res::PrimTy(hir::PrimTy::Bool), - span, - segments: self.arena.alloc_from_iter([hir::PathSegment { - ident: Ident { name: sym::bool, span }, - hir_id: bool_id, - res: Res::PrimTy(hir::PrimTy::Bool), - args: None, - infer_args: false, - }]), - }), - )), - )), - default: Some(hir::AnonConst { - def_id: anon_const, - hir_id: const_id, - body: const_body, - }), - is_host_effect: true, - }, - colon_span: None, - pure_wrt_drop: false, - source: hir::GenericParamSource::Generics, - }; - - params.push(param); - } - let lowered_generics = self.arena.alloc(hir::Generics { params: self.arena.alloc_from_iter(params), predicates: self.arena.alloc_from_iter(predicates), @@ -1673,4 +1625,70 @@ impl<'hir> LoweringContext<'_, 'hir> { } } } + + fn make_host_effect_param( + &mut self, + span: Span, + hir_id: hir::HirId, + def_id: LocalDefId, + ) -> hir::GenericParam<'hir> { + let const_node_id = self.next_node_id(); + let anon_const = + self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); + + let const_id = self.next_id(); + let const_expr_id = self.next_id(); + let bool_id = self.next_id(); + + self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); + self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); + + let const_body = self.lower_body(|this| { + ( + &[], + hir::Expr { + hir_id: const_expr_id, + kind: hir::ExprKind::Lit( + this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }), + ), + span, + }, + ) + }); + + hir::GenericParam { + def_id, + hir_id, + name: hir::ParamName::Plain(Ident { name: sym::host, span }), + span, + kind: hir::GenericParamKind::Const { + ty: self.arena.alloc(self.ty( + span, + hir::TyKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + res: Res::PrimTy(hir::PrimTy::Bool), + span, + segments: self.arena.alloc_from_iter([hir::PathSegment { + ident: Ident { name: sym::bool, span }, + hir_id: bool_id, + res: Res::PrimTy(hir::PrimTy::Bool), + args: None, + infer_args: false, + }]), + }), + )), + )), + default: Some(hir::AnonConst { + def_id: anon_const, + hir_id: const_id, + body: const_body, + }), + is_host_effect: true, + }, + colon_span: None, + pure_wrt_drop: false, + source: hir::GenericParamSource::Generics, + } + } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c679ee56fcd8b..fdd7a699a9b1b 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -27,6 +27,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // constness of the impl/bound if this is a trait path constness: Option, ) -> hir::QPath<'hir> { + // FIXME(effects): The name isn't great. + let trait_constness = qself.as_ref().map(|q| q.constness); let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -76,8 +78,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, parenthesized_generic_args, itctx, - // if this is the last segment, add constness to the trait path - if i == proj_start - 1 { constness } else { None }, + // If this is the last segment, add constness to the trait path. + // FIXME(effects): Is it possible that both constnesses are Some? + if i == proj_start - 1 { constness } else { trait_constness }, ) }, )), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f4b424259deef..e762eb62c49f0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1377,6 +1377,9 @@ impl<'a> State<'a> { if qself.position > 0 { self.space(); self.word_space("as"); + if qself.constness != ast::BoundConstness::Never { + self.word_space(qself.constness.as_str()); + } let depth = path.segments.len() - qself.position; self.print_path(path, false, depth); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3b..d940dfc1dc7a3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -304,6 +304,10 @@ impl GenericArg<'_> { GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true, } } + + pub fn is_desugared_from_effects(&self) -> bool { + matches!(self, GenericArg::Const(ConstArg { is_desugared_from_effects: true, .. })) + } } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -381,10 +385,8 @@ impl<'hir> GenericArgs<'hir> { pub fn num_generic_params(&self) -> usize { self.args .iter() - .filter(|arg| match arg { - GenericArg::Lifetime(_) - | GenericArg::Const(ConstArg { is_desugared_from_effects: true, .. }) => false, - _ => true, + .filter(|arg| { + !matches!(arg, GenericArg::Lifetime(_)) && !arg.is_desugared_from_effects() }) .count() } @@ -505,6 +507,14 @@ pub struct GenericParam<'hir> { } impl<'hir> GenericParam<'hir> { + pub fn has_default(&self) -> bool { + matches!( + self.kind, + GenericParamKind::Type { default: Some(_), .. } + | GenericParamKind::Const { default: Some(_), .. } + ) + } + /// Synthetic type-parameters are inserted after normal ones. /// In order for normal parameters to be able to refer to synthetic ones, /// scans them first. @@ -518,6 +528,10 @@ impl<'hir> GenericParam<'hir> { pub fn is_elided_lifetime(&self) -> bool { matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided }) } + + pub fn is_host_effect(&self) -> bool { + matches!(self.kind, GenericParamKind::Const { is_host_effect: true, .. }) + } } /// Records where the generic parameter originated from. diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index e2cd4d5f21c76..63c11fb894520 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -199,35 +199,26 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // If we have already computed the generic arguments for parents, // we can use those directly. while let Some(¶m) = params.peek() { - if let Some(&kind) = parent_args.get(param.index as usize) { - args.push(kind); - params.next(); - } else { - break; - } + let Some(&kind) = parent_args.get(param.index as usize) else { break }; + args.push(kind); + params.next(); } // `Self` is handled first, unless it's been handled in `parent_args`. - if has_self { - if let Some(¶m) = params.peek() { - if param.index == 0 { - if let GenericParamDefKind::Type { .. } = param.kind { - args.push( - self_ty - .map(|ty| ty.into()) - .unwrap_or_else(|| ctx.inferred_kind(None, param, true)), - ); - params.next(); - } - } - } + if has_self + && let Some(¶m) = params.peek() + && param.index == 0 + && let GenericParamDefKind::Type { .. } = param.kind + { + args.push( + self_ty.map(|ty| ty.into()).unwrap_or_else(|| ctx.inferred_kind(None, param, true)), + ); + params.next(); } // Check whether this segment takes generic arguments and the user has provided any. - let (generic_args, infer_args) = ctx.args_for_def_id(def_id); - - let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()); - let mut args_iter = args_iter.clone().peekable(); + let (hir_args, infer_args) = ctx.args_for_def_id(def_id); + let mut hir_args = hir_args.iter().flat_map(|args| args.args.iter()).peekable(); // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. // If we later encounter a lifetime, we know that the arguments were provided in the @@ -240,9 +231,25 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // provided, matching them with the generic parameters we expect. // Mismatches can occur as a result of elided lifetimes, or for malformed // input. We try to handle both sensibly. - match (args_iter.peek(), params.peek()) { + match (hir_args.peek(), params.peek()) { (Some(&arg), Some(¶m)) => { match (arg, ¶m.kind, arg_count.explicit_late_bound) { + ( + GenericArg::Type(_) + | GenericArg::Lifetime(_) + | GenericArg::Const(hir::ConstArg { + is_desugared_from_effects: false, + .. + }) + | GenericArg::Infer(_), + GenericParamDefKind::Const { is_host_effect: true, .. }, + _, + ) => { + // FIXME(fmease): Add explainer. + args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + params.next(); + } + // FIXME(fmease): This might no longer be necessary. ( GenericArg::Const(hir::ConstArg { is_desugared_from_effects: true, @@ -253,6 +260,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( | GenericParamDefKind::Lifetime, _, ) => { + // FIXME(fmease): This explainer is outdated. // SPECIAL CASE FOR DESUGARED EFFECT PARAMS // This comes from the following example: // @@ -280,7 +288,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( _, ) => { args.push(ctx.provided_kind(param, arg)); - args_iter.next(); + hir_args.next(); params.next(); } ( @@ -299,7 +307,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // the presence of explicit late bounds. This is most likely // due to the presence of the explicit bound so we're just going to // ignore it. - args_iter.next(); + hir_args.next(); } (_, _, _) => { // We expected one kind of parameter, but the user provided @@ -325,7 +333,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( tcx, arg, param, - !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()), + !hir_args.clone().is_sorted_by_key(|arg| arg.to_ord()), Some(format!( "reorder the arguments: {}: `<{}>`", param_types_present @@ -353,7 +361,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // errors. In this case, we're simply going to ignore the argument // and any following arguments. The rest of the parameters will be // inferred. - while args_iter.next().is_some() {} + while hir_args.next().is_some() {} } } } @@ -454,13 +462,8 @@ pub(crate) fn check_generic_arg_count( .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })) .count(); let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count; - let synth_const_param_count = gen_params - .params - .iter() - .filter(|param| { - matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. }) - }) - .count(); + let synth_const_param_count = + gen_params.params.iter().filter(|param| param.is_host_effect()).count(); let named_const_param_count = param_counts.consts - synth_const_param_count; let infer_lifetimes = (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650f9..cd3be34a718ce 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -539,7 +539,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Err(guar) = ty.error_reported() { return ty::Const::new_error(tcx, guar, ty).into(); } - // FIXME(effects) see if we should special case effect params here if !infer_args && has_default { tcx.const_param_default(param.def_id) .instantiate(tcx, args.unwrap()) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e557f36037b6c..95e63f0662e90 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1350,7 +1350,7 @@ fn impl_trait_ref( let last_segment = path_segments.len() - 1; let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; - assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); + assert!(args.args[last_arg].is_desugared_from_effects()); args.args = &args.args[..args.args.len() - 1]; path_segments[last_segment].args = Some(&args); let path = hir::Path { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index fde3d41faecf0..c5fc68d69d06d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -269,12 +269,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { ) -> Const<'tcx> { // FIXME ideally this shouldn't use unwrap match param { - Some( - param @ ty::GenericParamDef { - kind: ty::GenericParamDefKind::Const { is_host_effect: true, .. }, - .. - }, - ) => self.var_for_effect(param).as_const().unwrap(), + Some(param) if param.is_host_effect() => self.var_for_effect(param).as_const().unwrap(), Some(param) => self.var_for_def(span, param).as_const().unwrap(), None => self.next_const_var( ty, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index c746fb8af89a2..91759abc82a84 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -329,6 +329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if param.index == 0 { return self_ty.into(); } else if let Some(input_types) = opt_input_types { + // FIXME(fmease): IOOB when trying to build std...☠️ return input_types[param.index as usize - 1].into(); } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6807eacb7f177..e6fd857d8f218 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2254,7 +2254,7 @@ impl<'tcx> TyCtxt<'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), .. - }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })) + }) if generics.params.iter().rev().any(|param| param.is_host_effect()) ) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 4821ae3f08735..cc7846a4c6bf5 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -343,7 +343,7 @@ impl<'tcx> Generics { default.instantiate(tcx, args) == args[param.index as usize] }) // filter out trailing effect params, if we're not in `-Zverbose-internals`. - || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. })) + || (!verbose && param.is_host_effect()) }) .count(); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 720a610fdf518..3f926962c4595 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1791,7 +1791,10 @@ impl<'a> Parser<'a> { }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. - Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path))) + Ok(P(T::recovered( + Some(P(QSelf { ty, constness: ast::BoundConstness::Never, path_span, position: 0 })), + path, + ))) } pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index e7cad74b4dd14..f53c9f1d02e5b 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -58,16 +58,18 @@ impl PathStyle { } impl<'a> Parser<'a> { - /// Parses a qualified path. - /// Assumes that the leading `<` has been parsed already. + /// Parses a qualified path. Assumes that the leading `<` has been parsed already. /// - /// `qualified_path = ::path` + /// ```ebnf + /// QualifiedPath = "<" Type BoundConstness Path_type)? ">" "::" Path_$style + /// ``` /// /// # Examples - /// `::default` - /// `::a` - /// `::F::a` (without disambiguator) - /// `::F::a::` (with disambiguator) + /// + /// * `::default` + /// * `::a` + /// * `::F::a` (without disambiguator) + /// * `::F::a::` (with disambiguator) pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P, Path)> { let lo = self.prev_token.span; let ty = self.parse_ty()?; @@ -76,12 +78,14 @@ impl<'a> Parser<'a> { // if any (e.g., `U` in the `::*` examples // above). `path_span` has the span of that path, or an empty // span in the case of something like `::Bar`. - let (mut path, path_span); + let (constness, mut path, path_span); if self.eat_keyword(kw::As) { + constness = self.parse_bound_constness()?; let path_lo = self.token.span; path = self.parse_path(PathStyle::Type)?; path_span = path_lo.to(self.prev_token.span); } else { + constness = ast::BoundConstness::Never; path_span = self.token.span.to(self.token.span); path = ast::Path { segments: ThinVec::new(), span: path_span, tokens: None }; } @@ -97,7 +101,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; } - let qself = P(QSelf { ty, path_span, position: path.segments.len() }); + let qself = P(QSelf { ty, constness, path_span, position: path.segments.len() }); self.parse_path_segments(&mut path.segments, style, None)?; Ok(( diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a4fb92c67ac68..099de055e35bc 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -864,21 +864,11 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["?" | "!"] + /// TRAIT_BOUND_MODIFIERS = BOUND_CONSTNESS BOUND_POLARITY + /// BOUND_POLARITY = ["?" | "!"] /// ``` fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { - let constness = if self.eat(&token::Tilde) { - let tilde = self.prev_token.span; - self.expect_keyword(kw::Const)?; - let span = tilde.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::const_trait_impl, span); - BoundConstness::Maybe(span) - } else if self.eat_keyword(kw::Const) { - self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); - BoundConstness::Always(self.prev_token.span) - } else { - BoundConstness::Never - }; + let constness = self.parse_bound_constness()?; let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) @@ -892,6 +882,28 @@ impl<'a> Parser<'a> { Ok(TraitBoundModifiers { constness, polarity }) } + /// Parses the const modifiers that may precede a trait in a bound. + /// + /// If no modifiers are present, this doesn't consume any tokens. + /// + /// ```ebnf + /// BOUND_CONSTNESS = [["~"] "const"] + /// ``` + pub(crate) fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> { + Ok(if self.eat(&token::Tilde) { + let tilde = self.prev_token.span; + self.expect_keyword(kw::Const)?; + let span = tilde.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::const_trait_impl, span); + BoundConstness::Maybe(span) + } else if self.eat_keyword(kw::Const) { + self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); + BoundConstness::Always(self.prev_token.span) + } else { + BoundConstness::Never + }) + } + /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr deleted file mode 100644 index 62c8a442ab9bd..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.qualified.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-0.rs:21:6 - | -LL | ::Assoc::func() - | ^ the trait `Trait` is not implemented for `T` - | -help: consider further restricting this bound - | -LL | const fn qualified() -> i32 { - | +++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs index d8573d3af014c..f0547c3c58368 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-0.rs @@ -1,7 +1,4 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -// revisions: unqualified qualified -//[unqualified] check-pass -//[qualified] known-bug: unknown +// check-pass #![feature(const_trait_impl, effects)] @@ -11,14 +8,12 @@ trait Trait { fn func() -> i32; } -#[cfg(unqualified)] const fn unqualified() -> i32 { T::Assoc::func() } -#[cfg(qualified)] const fn qualified() -> i32 { - ::Assoc::func() + ::Assoc::func() } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs index 2190fa337b49f..5a3ad76beb229 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage-1.rs @@ -1,7 +1,4 @@ -// FIXME(effects): Collapse the revisions into one once we support `::Proj`. -// revisions: unqualified qualified -//[unqualified] check-pass -//[qualified] known-bug: unknown +// check-pass #![feature(const_trait_impl, effects, generic_const_exprs)] #![allow(incomplete_features)] @@ -14,13 +11,11 @@ trait Trait { struct Type; -#[cfg(unqualified)] fn unqualified() -> Type<{ T::Assoc::func() }> { Type } -#[cfg(qualified)] -fn qualified() -> Type<{ ::Assoc::func() }> { +fn qualified() -> Type<{ ::Assoc::func() }> { Type } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.always_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.maybe_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr new file mode 100644 index 0000000000000..7b6b7f119ae3e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.never_const_super.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: ~const Uwu` is not satisfied + --> $DIR/const-project.rs:11:33 + | +LL | pub trait Owo::K }> {} + | ^^^^ the trait `~const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Owo::K }>: ~const Uwu {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs new file mode 100644 index 0000000000000..dd784026c6470 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-project.rs @@ -0,0 +1,26 @@ +// revisions: never_const_super always_const_super maybe_const_super + +#![feature(const_trait_impl, effects)] +#![feature(associated_const_equality, generic_const_exprs)] +#![allow(incomplete_features)] + +// FIXME(effects): Shouldn't `{always,maybe}_const_super` pass? Also, why does +// the diagnostic message and location differ from `effects/project.rs`? + +#[const_trait] +pub trait Owo::K }> {} +//~^ ERROR the trait bound `Self: ~const Uwu` is not satisfied + +#[cfg(never_const_super)] +#[const_trait] +pub trait Uwu: Owo { const K: u32; } + +#[cfg(always_const_super)] +#[const_trait] +pub trait Uwu: const Owo { const K: u32; } + +#[cfg(maybe_const_super)] +#[const_trait] +pub trait Uwu: ~const Owo { const K: u32; } + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 84d9bcd7ac9f0..8a850a9cd1522 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -51,9 +51,8 @@ trait Try: FromResidual { fn branch(self) -> ControlFlow; } -// FIXME -// #[const_trait] -trait FromResidual::Residual> { +#[const_trait] +trait FromResidual::Residual> { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr new file mode 100644 index 0000000000000..7e81035e015bd --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always-const-super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:16 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:9:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr new file mode 100644 index 0000000000000..d7d8467703a4a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.always_const_super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:1 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:16 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:7:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error[E0277]: the trait bound `Self: const Uwu` is not satisfied + --> $DIR/project.rs:22:28 + | +LL | pub trait Uwu: const Owo { type T; } + | ^^^^^^^ the trait `const Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: const Owo + const Uwu { type T; } + | +++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr new file mode 100644 index 0000000000000..563eb3535c7a7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never-const-super.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:1 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:1 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:16 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^ the trait `Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:9:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:22 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:22 + | +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { type T; } + | +++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr similarity index 56% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr rename to tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr index eac3ee9e4e22b..b02af6b2cf2d8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.never_const_super.stderr @@ -1,63 +1,61 @@ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:1 | -LL | pub trait Uwu: Owo { +LL | pub trait Uwu: Owo { type T; } | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:1 | -LL | / pub trait Uwu: Owo { -LL | | type T; -LL | | } - | |_^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied --> $DIR/project.rs:12:16 | -LL | pub trait Uwu: Owo { +LL | pub trait Uwu: Owo { type T; } | ^^^ the trait `Uwu` is not implemented for `Self` | note: required by a bound in `Owo` - --> $DIR/project.rs:9:15 + --> $DIR/project.rs:7:15 | -LL | pub trait Owo::T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 + --> $DIR/project.rs:12:22 | -LL | type T; - | ^^^^^^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error[E0277]: the trait bound `Self: Uwu` is not satisfied - --> $DIR/project.rs:13:5 + --> $DIR/project.rs:12:22 | -LL | type T; - | ^^^^^^^ the trait `Uwu` is not implemented for `Self` +LL | pub trait Uwu: Owo { type T; } + | ^^^^^^^ the trait `Uwu` is not implemented for `Self` | help: consider further restricting `Self` | -LL | pub trait Uwu: Owo + Uwu { +LL | pub trait Uwu: Owo + Uwu { type T; } | +++++ error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs index e22eed3e0ef57..29841947f6a79 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -1,16 +1,33 @@ -// known-bug: #110395 -// FIXME: effects +// revisions: never_const_super always_const_super maybe_const_super +//[maybe_const_super] check-pass #![feature(const_trait_impl, effects)] +#[const_trait] +pub trait Owo::T> {} + // This fails because `~const Uwu` doesn't imply (non-const) `Uwu`. +#[cfg(never_const_super)] +#[const_trait] +pub trait Uwu: Owo { type T; } +//[never_const_super]~^ ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied +//[never_const_super]~| ERROR the trait bound `Self: Uwu` is not satisfied -// FIXME: #[const_trait] -pub trait Owo::T> {} +// FIXME(effects): Shouldn't this pass? +#[cfg(always_const_super)] +#[const_trait] +pub trait Uwu: const Owo { type T; } +//[always_const_super]~^ ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +//[always_const_super]~| ERROR the trait bound `Self: const Uwu` is not satisfied +#[cfg(maybe_const_super)] #[const_trait] -pub trait Uwu: Owo { - type T; -} +pub trait Uwu: ~const Owo { type T; } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr index 12f9355e41d4e..f48ef926e8d6c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:22:1 + --> $DIR/feature-gate.rs:27:1 | LL | fn main() {} | ^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs index 015d90aaf21fa..65261cf1494a7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs @@ -6,8 +6,8 @@ struct S; #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder -trait T {} -impl const T for S {} +trait T { type P; } +impl const T for S { type P = (); } //[stock]~^ ERROR const trait impls are experimental const fn f() {} //[stock]~ ERROR const trait impls are experimental @@ -18,5 +18,10 @@ macro_rules! discard { ($ty:ty) => {} } discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental discard! { impl const T } //[stock]~ ERROR const trait impls are experimental +const fn const_qualified_paths() { + let _: ::P; //[stock]~ ERROR const trait impls are experimental + let _: ::P; //[stock]~ ERROR const trait impls are experimental +} + #[rustc_error] fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr index 78157d5705638..e9e2afbab0db1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -1,7 +1,7 @@ error[E0658]: const trait impls are experimental --> $DIR/feature-gate.rs:10:6 | -LL | impl const T for S {} +LL | impl const T for S { type P = (); } | ^^^^^ | = note: see issue #67792 for more information @@ -28,6 +28,26 @@ LL | fn g() {} = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:22:18 + | +LL | let _: ::P; + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:23:18 + | +LL | let _: ::P; + | ^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: const trait impls are experimental --> $DIR/feature-gate.rs:18:17 | @@ -58,6 +78,6 @@ LL | #[const_trait] = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`.