From 8660832086db649e5a7e489ab40f303fa3f6638e Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 25 Aug 2021 11:53:16 +0000 Subject: [PATCH 01/10] Introduce `~const` - [x] Removed `?const` and change uses of `?const` - [x] Added `~const` to the AST. It is gated behind const_trait_impl. - [x] Validate `~const` in ast_validation. - [ ] Add enum `BoundConstness` to the HIR. (With variants `NotConst` and `ConstIfConst` allowing future extensions) - [ ] Adjust trait selection and pre-existing code to use `BoundConstness`. - [ ] Optional steps (*for this PR, obviously*) - [ ] Fix #88155 - [ ] Do something with constness bounds in chalk --- compiler/rustc_ast/src/ast.rs | 6 +- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 152 ++++++++++++------ compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_feature/src/active.rs | 3 - compiler/rustc_feature/src/removed.rs | 3 + compiler/rustc_middle/src/ty/mod.rs | 7 +- compiler/rustc_parse/src/parser/ty.rs | 46 +++--- compiler/rustc_typeck/src/collect.rs | 8 +- src/librustdoc/html/format.rs | 2 +- src/test/ui/consts/const-eval/issue-49296.rs | 13 +- .../call-generic-method-nonconst-opt-out.rs | 4 +- .../tilde-const-on-non-const-fn.rs | 12 ++ .../tilde-const-on-non-const-fn.stderr | 18 +++ src/tools/rustfmt/src/types.rs | 4 +- src/tools/rustfmt/tests/target/type.rs | 22 ++- 16 files changed, 178 insertions(+), 125 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2c2d30d872e20..2b86128b3f793 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -284,7 +284,7 @@ impl ParenthesizedArgs { pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; -/// A modifier on a bound, e.g., `?Sized` or `?const Trait`. +/// A modifier on a bound, e.g., `?Sized` or `~const Trait`. /// /// Negative bounds should also be handled here. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] @@ -295,10 +295,10 @@ pub enum TraitBoundModifier { /// `?Trait` Maybe, - /// `?const Trait` + /// `~const Trait` MaybeConst, - /// `?const ?Trait` + /// `~const ?Trait` // // This parses but will be rejected during AST validation. MaybeConstMaybe, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7b0188755710b..948d74e3bf8eb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1414,7 +1414,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ref ty, TraitBoundModifier::None | TraitBoundModifier::MaybeConst, ) => Some(this.lower_poly_trait_ref(ty, itctx.reborrow())), - // `?const ?Bound` will cause an error during AST validation + // `~const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( _, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index cff1b70dda907..2658971ecb0e8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -17,10 +17,11 @@ use rustc_errors::{error_code, pluralize, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::Session; +use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; +use std::convert::TryInto; use std::mem; use std::ops::DerefMut; @@ -33,24 +34,6 @@ enum SelfSemantic { No, } -/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`). -#[derive(Clone, Copy)] -enum BoundContext { - ImplTrait, - TraitBounds, - TraitObject, -} - -impl BoundContext { - fn description(&self) -> &'static str { - match self { - Self::ImplTrait => "`impl Trait`", - Self::TraitBounds => "supertraits", - Self::TraitObject => "trait objects", - } - } -} - struct AstValidator<'a> { session: &'a Session, @@ -60,6 +43,8 @@ struct AstValidator<'a> { /// Are we inside a trait impl? in_trait_impl: bool, + in_const_trait_impl: bool, + has_proc_macro_decls: bool, /// Used to ban nested `impl Trait`, e.g., `impl Into`. @@ -67,11 +52,7 @@ struct AstValidator<'a> { /// e.g., `impl Iterator`. outer_impl_trait: Option, - /// Keeps track of the `BoundContext` as we recurse. - /// - /// This is used to forbid `?const Trait` bounds in, e.g., - /// `impl Iterator`. - bound_context: Option, + is_tilde_const_allowed: bool, /// Used to ban `impl Trait` in path projections like `::Item` /// or `Foo::Bar` @@ -88,10 +69,18 @@ struct AstValidator<'a> { } impl<'a> AstValidator<'a> { - fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) { + fn with_in_trait_impl( + &mut self, + is_in: bool, + constness: Option, + f: impl FnOnce(&mut Self), + ) { let old = mem::replace(&mut self.in_trait_impl, is_in); + let old_const = + mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_)))); f(self); self.in_trait_impl = old; + self.in_const_trait_impl = old_const; } fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) { @@ -100,6 +89,18 @@ impl<'a> AstValidator<'a> { self.is_impl_trait_banned = old; } + fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { + let old = mem::replace(&mut self.is_tilde_const_allowed, true); + f(self); + self.is_tilde_const_allowed = old; + } + + fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) { + let old = mem::replace(&mut self.is_tilde_const_allowed, false); + f(self); + self.is_tilde_const_allowed = old; + } + fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) { let old = mem::replace(&mut self.is_let_allowed, allowed); f(self, old); @@ -130,19 +131,13 @@ impl<'a> AstValidator<'a> { fn with_impl_trait(&mut self, outer: Option, f: impl FnOnce(&mut Self)) { let old = mem::replace(&mut self.outer_impl_trait, outer); if outer.is_some() { - self.with_bound_context(BoundContext::ImplTrait, |this| f(this)); + self.with_banned_tilde_const(f); } else { - f(self) + f(self); } self.outer_impl_trait = old; } - fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) { - let old = self.bound_context.replace(ctx); - f(self); - self.bound_context = old; - } - fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) { match constraint.kind { AssocTyConstraintKind::Equality { .. } => {} @@ -164,9 +159,7 @@ impl<'a> AstValidator<'a> { TyKind::ImplTrait(..) => { self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) } - TyKind::TraitObject(..) => { - self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t)); - } + TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)), TyKind::Path(ref qself, ref path) => { // We allow these: // - `Option` @@ -1083,13 +1076,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { unsafety, polarity, defaultness: _, - constness: _, - generics: _, + constness, + ref generics, of_trait: Some(ref t), ref self_ty, - items: _, + ref items, }) => { - self.with_in_trait_impl(true, |this| { + self.with_in_trait_impl(true, Some(constness), |this| { this.invalid_visibility(&item.vis, None); if let TyKind::Err = self_ty.kind { this.err_handler() @@ -1112,7 +1105,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .emit(); } - visit::walk_item(this, item); + this.visit_vis(&item.vis); + this.visit_ident(item.ident); + if let Const::Yes(_) = constness { + this.with_tilde_const_allowed(|this| this.visit_generics(generics)); + } else { + this.visit_generics(generics); + } + this.visit_trait_ref(t); + this.visit_ty(self_ty); + + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); }); return; // Avoid visiting again. } @@ -1157,13 +1160,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .emit(); } } - ItemKind::Fn(box FnKind(def, _, _, ref body)) => { + ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => { self.check_defaultness(item.span, def); if body.is_none() { let msg = "free function without a body"; self.error_item_without_body(item.span, "function", msg, " { }"); } + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + if let Const::Yes(_) = sig.header.constness { + self.with_tilde_const_allowed(|this| this.visit_generics(generics)); + } else { + self.visit_generics(generics); + } + let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref()); + self.visit_fn(kind, item.span, item.id); + walk_list!(self, visit_attribute, &item.attrs); } ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); @@ -1206,9 +1219,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); - self.with_bound_context(BoundContext::TraitBounds, |this| { - walk_list!(this, visit_param_bound, bounds); - }); + self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds)); walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1281,7 +1292,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { _ => {} } - visit::walk_item(self, item) + visit::walk_item(self, item); } fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { @@ -1428,15 +1439,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_param_bound(&mut self, bound: &'a GenericBound) { match bound { GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => { - if let Some(ctx) = self.bound_context { - let msg = format!("`?const` is not permitted in {}", ctx.description()); - self.err_handler().span_err(bound.span(), &msg); + if !self.is_tilde_const_allowed { + let msg = "`~const` is not allowed here"; + let id_span_msg = ( + DiagnosticMessageId::StabilityId(67792.try_into().ok()), + Some(bound.span()), + msg.to_owned(), + ); + let fresh = self.session.one_time_diagnostics.borrow_mut().insert(id_span_msg); + if fresh { + self.err_handler() + .struct_span_err(bound.span(), msg) + .note("only allowed on bounds on traits' associated types, const fns, const impls and its associated functions") + .emit(); + } } } GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => { self.err_handler() - .span_err(bound.span(), "`?const` and `?` are mutually exclusive"); + .span_err(bound.span(), "`~const` and `?` are mutually exclusive"); } _ => {} @@ -1589,7 +1611,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_item_named(item.ident, "const"); } - self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt)); + match item.kind { + AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) + if ctxt == AssocCtxt::Trait => + { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + walk_list!(self, visit_attribute, &item.attrs); + self.with_tilde_const_allowed(|this| { + this.visit_generics(generics); + walk_list!(this, visit_param_bound, bounds); + }); + walk_list!(self, visit_ty, ty); + } + AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) + if self.in_const_trait_impl => + { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.with_tilde_const_allowed(|this| this.visit_generics(generics)); + let kind = + FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref()); + self.visit_fn(kind, item.span, item.id); + } + _ => self + .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)), + } } } @@ -1683,9 +1730,10 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> session, extern_mod: None, in_trait_impl: false, + in_const_trait_impl: false, has_proc_macro_decls: false, outer_impl_trait: None, - bound_context: None, + is_tilde_const_allowed: false, is_impl_trait_banned: false, is_assoc_ty_bound_banned: false, is_let_allowed: false, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0be26b6f8e9de..557271e32adb4 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -656,7 +656,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(generators, "yield syntax is experimental"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); - gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds 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!(inline_const, "inline-const is experimental"); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 4f4baf2877df7..5ae106353da61 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -515,9 +515,6 @@ declare_features! ( /// Allows `impl const Trait for T` syntax. (active, const_trait_impl, "1.42.0", Some(67792), None), - /// Allows `T: ?const Trait` syntax in bounds. - (incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None), - /// Allows the use of `no_sanitize` attribute. (active, no_sanitize, "1.42.0", Some(39699), None), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 5cadbd9e5cf71..a8aa3c606c6c0 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -123,6 +123,9 @@ declare_features! ( /// Allows overlapping impls of marker traits. (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, Some("removed in favor of `#![feature(marker_trait_attr)]`")), + /// Allows `T: ?const Trait` syntax in bounds. + (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None, + Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), /// Allows comparing raw pointers during const eval. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8f814a84b4959..c8ca08f9762b2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -457,10 +457,6 @@ pub enum PredicateKind<'tcx> { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. - /// - /// A trait predicate will have `Constness::Const` if it originates - /// from a bound on a `const fn` without the `?const` opt-out (e.g., - /// `const fn foobar() {}`). Trait(TraitPredicate<'tcx>), /// `where 'a: 'b` @@ -633,8 +629,7 @@ pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, /// A trait predicate will have `Constness::Const` if it originates - /// from a bound on a `const fn` without the `?const` opt-out (e.g., - /// `const fn foobar() {}`). + /// from a bound marked with `~const`. pub constness: hir::Constness, } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1fbf01b1b97d5..299fc916ac97f 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -11,12 +11,12 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym}; -/// Any `?` or `?const` modifiers that appear at the start of a bound. +/// Any `?` or `~const` modifiers that appear at the start of a bound. struct BoundModifiers { /// `?Trait`. maybe: Option, - /// `?const Trait`. + /// `~const Trait`. maybe_const: Option, } @@ -609,6 +609,7 @@ impl<'a> Parser<'a> { || self.check_lifetime() || self.check(&token::Not) // Used for error reporting only. || self.check(&token::Question) + || self.check(&token::Tilde) || self.check_keyword(kw::For) || self.check(&token::OpenDelim(token::Paren)) } @@ -655,7 +656,7 @@ impl<'a> Parser<'a> { let inner_lo = self.token.span; let is_negative = self.eat(&token::Not); - let modifiers = self.parse_ty_bound_modifiers(); + let modifiers = self.parse_ty_bound_modifiers()?; let bound = if self.token.is_lifetime() { self.error_lt_bound_with_modifiers(modifiers); self.parse_generic_lt_bound(lo, inner_lo, has_parens)? @@ -690,7 +691,7 @@ impl<'a> Parser<'a> { if let Some(span) = modifiers.maybe_const { self.struct_span_err( span, - "`?const` may only modify trait bounds, not lifetime bounds", + "`~const` may only modify trait bounds, not lifetime bounds", ) .emit(); } @@ -721,34 +722,27 @@ impl<'a> Parser<'a> { Ok(()) } - /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `?const Trait`. + /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `~const Trait`. /// /// If no modifiers are present, this does not consume any tokens. /// /// ``` - /// TY_BOUND_MODIFIERS = "?" ["const" ["?"]] + /// TY_BOUND_MODIFIERS = ["~const"] ["?"] /// ``` - fn parse_ty_bound_modifiers(&mut self) -> BoundModifiers { - if !self.eat(&token::Question) { - return BoundModifiers { maybe: None, maybe_const: None }; - } - - // `? ...` - let first_question = self.prev_token.span; - if !self.eat_keyword(kw::Const) { - return BoundModifiers { maybe: Some(first_question), maybe_const: None }; - } + fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> { + let maybe_const = 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); + Some(span) + } else { + None + }; - // `?const ...` - let maybe_const = first_question.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::const_trait_bound_opt_out, maybe_const); - if !self.eat(&token::Question) { - return BoundModifiers { maybe: None, maybe_const: Some(maybe_const) }; - } + let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None }; - // `?const ? ...` - let second_question = self.prev_token.span; - BoundModifiers { maybe: Some(second_question), maybe_const: Some(maybe_const) } + Ok(BoundModifiers { maybe, maybe_const }) } /// Parses a type bound according to: @@ -757,7 +751,7 @@ impl<'a> Parser<'a> { /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for] SIMPLE_PATH /// ``` /// - /// For example, this grammar accepts `?const ?for<'a: 'b> m::Trait<'a>`. + /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`. fn parse_generic_ty_bound( &mut self, lo: Span, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 75f9405e082ca..3ae26c3eb78e0 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2227,8 +2227,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { let constness = match modifier { - hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst, - hir::TraitBoundModifier::None => constness, + hir::TraitBoundModifier::None => hir::Constness::NotConst, + hir::TraitBoundModifier::MaybeConst => constness, // We ignore `where T: ?Sized`, it is already part of // type parameter `T`. hir::TraitBoundModifier::Maybe => continue, @@ -2497,8 +2497,8 @@ fn predicates_from_bound<'tcx>( hir::GenericBound::Trait(ref tr, modifier) => { let constness = match modifier { hir::TraitBoundModifier::Maybe => return vec![], - hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst, - hir::TraitBoundModifier::None => constness, + hir::TraitBoundModifier::MaybeConst => constness, + hir::TraitBoundModifier::None => hir::Constness::NotConst, }; let mut bounds = Bounds::default(); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index eb7c12d13c339..54be830bf42e7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -387,7 +387,7 @@ impl clean::GenericBound { let modifier_str = match modifier { hir::TraitBoundModifier::None => "", hir::TraitBoundModifier::Maybe => "?", - hir::TraitBoundModifier::MaybeConst => "?const", + hir::TraitBoundModifier::MaybeConst => "~const", }; if f.alternate() { write!(f, "{}{:#}", modifier_str, ty.print(cx)) diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs index bb8113e53f9c1..80f6bbec2a181 100644 --- a/src/test/ui/consts/const-eval/issue-49296.rs +++ b/src/test/ui/consts/const-eval/issue-49296.rs @@ -1,22 +1,13 @@ // issue-49296: Unsafe shenigans in constants can result in missing errors #![feature(const_fn_trait_bound)] -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] -const unsafe fn transmute(t: T) -> U { - #[repr(C)] - union Transmute { - from: T, - to: U, - } - - Transmute { from: t }.to -} +use std::mem::transmute; const fn wat(x: u64) -> &'static u64 { unsafe { transmute(&x) } } + const X: u64 = *wat(42); //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs index 1fc2c4fe4456f..8a0f39acf2583 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs @@ -13,12 +13,10 @@ impl PartialEq for S { } } -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { true } pub const EQ: bool = equals_self(&S); -// Calling `equals_self` with a type that only has a non-const impl is fine, because we opted out. - fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs new file mode 100644 index 0000000000000..cde5233d4c88b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs @@ -0,0 +1,12 @@ +#![feature(const_trait_impl)] +fn a>() {} +//~^ ERROR: `~const` is not allowed + +struct S; + +impl S { + fn b>() {} + //~^ ERROR: `~const` is not allowed +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr new file mode 100644 index 0000000000000..4f81a607f6eaf --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr @@ -0,0 +1,18 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-on-non-const-fn.rs:2:9 + | +LL | fn a>() {} + | ^^^^^^^^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-on-non-const-fn.rs:8:13 + | +LL | fn b>() {} + | ^^^^^^^^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: aborting due to 2 previous errors + diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index c6f89c310650c..640d127e86098 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -537,10 +537,10 @@ impl Rewrite for ast::GenericBound { .map(|s| format!("?{}", s)), ast::TraitBoundModifier::MaybeConst => poly_trait_ref .rewrite(context, shape.offset_left(7)?) - .map(|s| format!("?const {}", s)), + .map(|s| format!("~const {}", s)), ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref .rewrite(context, shape.offset_left(8)?) - .map(|s| format!("?const ?{}", s)), + .map(|s| format!("~const ?{}", s)), }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } diff --git a/src/tools/rustfmt/tests/target/type.rs b/src/tools/rustfmt/tests/target/type.rs index e7761251688a9..9ab66944c8ccc 100644 --- a/src/tools/rustfmt/tests/target/type.rs +++ b/src/tools/rustfmt/tests/target/type.rs @@ -145,35 +145,33 @@ type MyFn = fn( b: SomeOtherLongComplexType, ) -> Box>; -// Const opt-out +// Const bound -trait T: ?const Super {} +trait T: ~const Super {} -const fn maybe_const() -> i32 { +const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); +struct S(std::marker::PhantomData); -impl ?const T {} +impl ~const T {} -fn trait_object() -> &'static dyn ?const T { +fn trait_object() -> &'static dyn ~const T { &S } -fn i(_: impl IntoIterator>) {} +fn i(_: impl IntoIterator>) {} -fn apit(_: impl ?const T) {} +fn apit(_: impl ~const T) {} -fn rpit() -> impl ?const T { +fn rpit() -> impl ~const T { S } pub struct Foo(T); -impl Foo { +impl Foo { fn new(t: T) -> Self { - // not calling methods on `t`, so we opt out of requiring - // `` to have const methods via `?const` Self(t) } } From 1164c946b0a5889f6f0ca1dba48db0cf36c32915 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 25 Aug 2021 13:38:14 +0000 Subject: [PATCH 02/10] Fix visiting twice --- .../rustc_ast_passes/src/ast_validation.rs | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2658971ecb0e8..c0ea710fdcb4e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -17,11 +17,10 @@ use rustc_errors::{error_code, pluralize, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::{DiagnosticMessageId, Session}; +use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; -use std::convert::TryInto; use std::mem; use std::ops::DerefMut; @@ -1177,6 +1176,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref()); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); + return; // Avoid visiting again. } ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); @@ -1440,19 +1440,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match bound { GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => { if !self.is_tilde_const_allowed { - let msg = "`~const` is not allowed here"; - let id_span_msg = ( - DiagnosticMessageId::StabilityId(67792.try_into().ok()), - Some(bound.span()), - msg.to_owned(), - ); - let fresh = self.session.one_time_diagnostics.borrow_mut().insert(id_span_msg); - if fresh { - self.err_handler() - .struct_span_err(bound.span(), msg) - .note("only allowed on bounds on traits' associated types, const fns, const impls and its associated functions") - .emit(); - } + self.err_handler() + .struct_span_err(bound.span(), "`~const` is not allowed here") + .note("only allowed on bounds on traits' associated types, const fns, const impls and its associated functions") + .emit(); } } From ff24ac4f2b1415cc93e0cc3edb70097df6dae073 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 25 Aug 2021 14:30:09 +0000 Subject: [PATCH 03/10] Try fixing some tests --- .../call-generic-method-dup-bound.rs | 6 +-- .../call-generic-method-fail.rs | 4 +- ... => call-generic-method-nonconst-bound.rs} | 3 -- .../feature-gate.gated.stderr | 8 ---- .../const-trait-bound-opt-out/feature-gate.rs | 17 --------- .../feature-gate.stock.stderr | 12 ------ .../in-impl-trait.rs | 21 ---------- .../in-impl-trait.stderr | 26 ------------- .../in-trait-bounds.rs | 8 ---- .../in-trait-bounds.stderr | 8 ---- .../in-trait-object.rs | 19 ---------- .../in-trait-object.stderr | 20 ---------- .../opt-out-twice.rs | 8 ---- .../opt-out-twice.stderr | 14 ------- .../const-trait-bound-opt-out/syntax.rs | 10 ----- .../with-maybe-sized.rs | 7 ---- .../with-maybe-sized.stderr | 8 ---- .../without-question-mark.rs | 7 ---- .../without-question-mark.stderr | 8 ---- .../impl-opt-out-trait.stderr | 8 ---- ...out-trait.rs => impl-tilde-const-trait.rs} | 4 +- .../inherent-impl.rs | 2 - .../ui/rfc-2632-const-trait-impl/syntax.rs | 2 +- .../tilde-const-invalid-places.rs | 38 +++++++++++++++++++ .../tilde-const-on-non-const-fn.rs | 12 ------ .../tilde-const-on-non-const-fn.stderr | 18 --------- .../tilde-const-syntax.rs | 9 +++++ 27 files changed, 52 insertions(+), 255 deletions(-) rename src/test/ui/rfc-2632-const-trait-impl/{call-generic-method-nonconst-opt-out.rs => call-generic-method-nonconst-bound.rs} (71%) delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr rename src/test/ui/rfc-2632-const-trait-impl/{impl-opt-out-trait.rs => impl-tilde-const-trait.rs} (53%) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index 00a3c7f51fe90..5853b66b868a5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -1,9 +1,7 @@ // check-pass #![feature(const_trait_impl)] -#![feature(const_trait_bound_opt_out)] #![feature(const_fn_trait_bound)] -#![allow(incomplete_features)] struct S; @@ -16,9 +14,9 @@ impl const PartialEq for S { } } -// This duplicate bound should not result in ambiguities. It should be equivalent to a single const +// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const // bound. -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs index dc4d5561d4745..e96249ff2fd5a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -1,9 +1,7 @@ #![feature(const_fn_trait_bound)] #![feature(const_trait_impl)] -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] -pub const fn equals_self(t: &T) -> bool { +pub const fn equals_self(t: &T) -> bool { *t == *t //~^ ERROR calls in constant functions are limited to constant functions } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs similarity index 71% rename from src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs rename to src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs index 8a0f39acf2583..585b65988f390 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs @@ -1,9 +1,6 @@ // check-pass #![feature(const_fn_trait_bound)] -#![feature(const_trait_impl)] -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr deleted file mode 100644 index 58041454d5901..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:17:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs deleted file mode 100644 index 4452ad7ea239c..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs +++ /dev/null @@ -1,17 +0,0 @@ -// revisions: stock gated -// gate-test-const_trait_bound_opt_out - -#![cfg_attr(gated, feature(const_trait_bound_opt_out))] -#![allow(incomplete_features)] -#![feature(rustc_attrs)] -#![feature(const_fn_trait_bound)] - -trait T { - const CONST: i32; -} - -const fn get_assoc_const() -> i32 { ::CONST } -//[stock]~^ ERROR `?const` on trait bounds is experimental - -#[rustc_error] -fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr deleted file mode 100644 index 8ae8b8868dded..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: `?const` on trait bounds is experimental - --> $DIR/feature-gate.rs:13:29 - | -LL | const fn get_assoc_const() -> i32 { ::CONST } - | ^^^^^^ - | - = note: see issue #67794 for more information - = help: add `#![feature(const_trait_bound_opt_out)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs deleted file mode 100644 index f5561a922ddcd..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(const_trait_bound_opt_out)] -#![feature(associated_type_bounds)] -#![allow(incomplete_features)] - -trait T {} -struct S; -impl T for S {} - -fn rpit() -> impl ?const T { S } -//~^ ERROR `?const` is not permitted in `impl Trait` - -fn apit(_: impl ?const T) {} -//~^ ERROR `?const` is not permitted in `impl Trait` - -fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } -//~^ ERROR `?const` is not permitted in `impl Trait` - -fn apit_assoc_bound(_: impl IntoIterator) {} -//~^ ERROR `?const` is not permitted in `impl Trait` - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr deleted file mode 100644 index 06cd00a956a2d..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:9:19 - | -LL | fn rpit() -> impl ?const T { S } - | ^^^^^^^^ - -error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:12:17 - | -LL | fn apit(_: impl ?const T) {} - | ^^^^^^^^ - -error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:15:50 - | -LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } - | ^^^^^^^^ - -error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:18:48 - | -LL | fn apit_assoc_bound(_: impl IntoIterator) {} - | ^^^^^^^^ - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs deleted file mode 100644 index fc9ed5b1dc22e..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] - -trait Super {} -trait T: ?const Super {} -//~^ ERROR `?const` is not permitted in supertraits - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr deleted file mode 100644 index a0d8f95acd2a8..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `?const` is not permitted in supertraits - --> $DIR/in-trait-bounds.rs:5:10 - | -LL | trait T: ?const Super {} - | ^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs deleted file mode 100644 index b3d1f48ace147..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(const_trait_bound_opt_out)] -#![allow(bare_trait_objects)] -#![allow(incomplete_features)] - -struct S; -trait T {} -impl T for S {} - -// An inherent impl for the trait object `?const T`. -impl ?const T {} -//~^ ERROR `?const` is not permitted in trait objects - -fn trait_object() -> &'static dyn ?const T { &S } -//~^ ERROR `?const` is not permitted in trait objects - -fn trait_object_in_apit(_: impl IntoIterator>) {} -//~^ ERROR `?const` is not permitted in trait objects - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr deleted file mode 100644 index 331fe0423fa94..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: `?const` is not permitted in trait objects - --> $DIR/in-trait-object.rs:10:6 - | -LL | impl ?const T {} - | ^^^^^^^^ - -error: `?const` is not permitted in trait objects - --> $DIR/in-trait-object.rs:13:35 - | -LL | fn trait_object() -> &'static dyn ?const T { &S } - | ^^^^^^^^ - -error: `?const` is not permitted in trait objects - --> $DIR/in-trait-object.rs:16:61 - | -LL | fn trait_object_in_apit(_: impl IntoIterator>) {} - | ^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs deleted file mode 100644 index 01e941a8fba45..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs +++ /dev/null @@ -1,8 +0,0 @@ -// compile-flags: -Z parse-only - -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] - -struct S; -//~^ ERROR expected identifier, found keyword `const` -//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>` diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr deleted file mode 100644 index f7924b3f24db3..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: expected identifier, found keyword `const` - --> $DIR/opt-out-twice.rs:6:21 - | -LL | struct S; - | ^^^^^ expected identifier, found keyword - -error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr` - --> $DIR/opt-out-twice.rs:6:27 - | -LL | struct S; - | ^^ expected one of 7 possible tokens - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs deleted file mode 100644 index a0d9610bbb5e2..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs +++ /dev/null @@ -1,10 +0,0 @@ -// compile-flags: -Z parse-only -// check-pass - -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] - -struct S< - T: ?const ?for<'a> Tr<'a> + 'static + ?const std::ops::Add, - T: ?const ?for<'a: 'b> m::Trait<'a>, ->; diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs deleted file mode 100644 index c2c8689e2942b..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] - -struct S(std::marker::PhantomData); -//~^ ERROR `?const` and `?` are mutually exclusive - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr deleted file mode 100644 index e8e9d6c1e7621..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `?const` and `?` are mutually exclusive - --> $DIR/with-maybe-sized.rs:4:13 - | -LL | struct S(std::marker::PhantomData); - | ^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs deleted file mode 100644 index b904a2eec0dd0..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs +++ /dev/null @@ -1,7 +0,0 @@ -// compile-flags: -Z parse-only - -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] - -struct S; -//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr deleted file mode 100644 index 0dbca952c037e..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found keyword `const` - --> $DIR/without-question-mark.rs:6:13 - | -LL | struct S; - | ^^^^^ expected one of 9 possible tokens - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr deleted file mode 100644 index 8f923efb093f3..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected a trait, found type - --> $DIR/impl-opt-out-trait.rs:8:6 - | -LL | impl ?const T for S {} - | ^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs similarity index 53% rename from src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs rename to src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs index 98d3a220d8674..05b26465c5b0c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs @@ -1,11 +1,9 @@ -#![feature(const_trait_bound_opt_out)] #![feature(const_trait_impl)] -#![allow(incomplete_features)] struct S; trait T {} -impl ?const T for S {} +impl ~const T for S {} //~^ ERROR expected a trait, found type fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs index 04123a532bd9f..afd0d137bb4aa 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs @@ -1,6 +1,4 @@ #![feature(const_trait_impl)] -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] #![allow(bare_trait_objects)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs index 82a1275bffaed..7ac2458e39928 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs @@ -5,4 +5,4 @@ #![feature(const_trait_impl)] // For now, this parses since an error does not occur until AST lowering. -impl ?const T {} +impl ~const T {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs new file mode 100644 index 0000000000000..a8912705d9458 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -0,0 +1,38 @@ +#![feature(const_trait_impl)] +#![feature(associated_type_bounds)] + +trait T {} +struct S; +impl T for S {} + +fn rpit() -> impl ~const T { S } +//~^ ERROR `~const` is not allowed + +fn apit(_: impl ~const T) {} +//~^ ERROR `~const` is not allowed + +fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } +//~^ ERROR `~const` is not allowed + +fn apit_assoc_bound(_: impl IntoIterator) {} +//~^ ERROR `~const` is not allowed + +fn generic() {} +//~^ ERROR `~const` is not allowed + +fn where_clause() where T: ~const T {} +//~^ ERROR `~const` is not allowed + +impl ~const T {} +//~^ ERROR `~const` is not allowed + +fn trait_object() -> &'static dyn ~const T { &S } +//~^ ERROR `~const` is not allowed + +fn trait_object_in_apit(_: impl IntoIterator>) {} +//~^ ERROR `~const` is not allowed + +struct S(std::marker::PhantomData); +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs deleted file mode 100644 index cde5233d4c88b..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(const_trait_impl)] -fn a>() {} -//~^ ERROR: `~const` is not allowed - -struct S; - -impl S { - fn b>() {} - //~^ ERROR: `~const` is not allowed -} - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr deleted file mode 100644 index 4f81a607f6eaf..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-on-non-const-fn.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: `~const` is not allowed here - --> $DIR/tilde-const-on-non-const-fn.rs:2:9 - | -LL | fn a>() {} - | ^^^^^^^^^^^^^^^ - | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions - -error: `~const` is not allowed here - --> $DIR/tilde-const-on-non-const-fn.rs:8:13 - | -LL | fn b>() {} - | ^^^^^^^^^^^^^^^ - | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs new file mode 100644 index 0000000000000..9b3c2cf2a3b04 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z parse-only +// check-pass + +#![feature(const_trait_impl)] + +struct S< + T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add, + T: ~const ?for<'a: 'b> m::Trait<'a>, +>; From 703c557aaa48ba647f6fafea2330819a8bbe6734 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 25 Aug 2021 15:21:55 +0000 Subject: [PATCH 04/10] Fix more tests --- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- .../ui/consts/const-eval/issue-49296.stderr | 2 +- .../projection-bound-cycle-generic.stderr | 8 +-- .../projection-bound-cycle.stderr | 8 +-- src/test/ui/parser/bounds-type.rs | 8 +-- src/test/ui/parser/bounds-type.stderr | 4 +- src/test/ui/parser/trait-object-delimiters.rs | 2 +- .../ui/parser/trait-object-delimiters.stderr | 4 +- .../rfc-2632-const-trait-impl/assoc-type.rs | 6 +- .../assoc-type.stderr | 8 +-- .../call-generic-in-impl.rs | 2 +- .../call-generic-method-chain.rs | 4 +- .../call-generic-method-fail.stderr | 2 +- .../call-generic-method-nonconst.rs | 2 +- .../call-generic-method-nonconst.stderr | 4 +- .../call-generic-method-pass.rs | 2 +- .../impl-tilde-const-trait.stderr | 8 +++ .../inherent-impl.stderr | 4 +- .../tilde-const-invalid-places.rs | 15 +---- .../tilde-const-invalid-places.stderr | 56 +++++++++++++++++++ 20 files changed, 103 insertions(+), 50 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index d916ff7db3d51..b7054d1562686 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -927,7 +927,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.instantiate_poly_trait_ref( &b.trait_ref, b.span, - constness, + Constness::NotConst, param_ty, bounds, false, @@ -937,7 +937,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.instantiate_poly_trait_ref( &b.trait_ref, b.span, - Constness::NotConst, + constness, param_ty, bounds, false, diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 28fdcb7c48637..bc3074b10bee6 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-49296.rs:20:16 + --> $DIR/issue-49296.rs:11:16 | LL | const X: u64 = *wat(42); | ^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr index 5e7e72ca562dd..2b57c439fe9a0 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -4,11 +4,11 @@ error[E0275]: overflow evaluating the requirement `::Item: Sized` LL | type Assoc = OnlySized<::Item>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required by a bound in `Foo::Item` - --> $DIR/projection-bound-cycle-generic.rs:11:49 +note: required by a bound in `OnlySized` + --> $DIR/projection-bound-cycle-generic.rs:28:18 | -LL | type Item: Sized where ::Item: Sized; - | ^^^^^ required by this bound in `Foo::Item` +LL | struct OnlySized where T: Sized { f: T } + | ^ required by this bound in `OnlySized` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index 1153bf53ba43e..d9d0bf4274bd7 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -4,11 +4,11 @@ error[E0275]: overflow evaluating the requirement `::Item: Sized` LL | type Assoc = OnlySized<::Item>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required by a bound in `Foo::Item` - --> $DIR/projection-bound-cycle.rs:13:49 +note: required by a bound in `OnlySized` + --> $DIR/projection-bound-cycle.rs:30:18 | -LL | type Item: Sized where ::Item: Sized; - | ^^^^^ required by this bound in `Foo::Item` +LL | struct OnlySized where T: Sized { f: T } + | ^ required by this bound in `OnlySized` error: aborting due to previous error diff --git a/src/test/ui/parser/bounds-type.rs b/src/test/ui/parser/bounds-type.rs index 7a187a0518af9..4ae4549ea5896 100644 --- a/src/test/ui/parser/bounds-type.rs +++ b/src/test/ui/parser/bounds-type.rs @@ -9,10 +9,10 @@ struct S< T: Tr +, // OK T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds - T: ?const Tr, // OK - T: ?const ?Tr, // OK - T: ?const Tr + 'a, // OK - T: ?const 'a, //~ ERROR `?const` may only modify trait bounds, not lifetime bounds + T: ~const Tr, // OK + T: ~const ?Tr, // OK + T: ~const Tr + 'a, // OK + T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds >; fn main() {} diff --git a/src/test/ui/parser/bounds-type.stderr b/src/test/ui/parser/bounds-type.stderr index 9a1f2ed398240..005bc1e54bd00 100644 --- a/src/test/ui/parser/bounds-type.stderr +++ b/src/test/ui/parser/bounds-type.stderr @@ -4,10 +4,10 @@ error: `?` may only modify trait bounds, not lifetime bounds LL | T: ?'a, | ^ -error: `?const` may only modify trait bounds, not lifetime bounds +error: `~const` may only modify trait bounds, not lifetime bounds --> $DIR/bounds-type.rs:15:8 | -LL | T: ?const 'a, +LL | T: ~const 'a, | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/trait-object-delimiters.rs b/src/test/ui/parser/trait-object-delimiters.rs index 650ab57226187..b5258eebb90ad 100644 --- a/src/test/ui/parser/trait-object-delimiters.rs +++ b/src/test/ui/parser/trait-object-delimiters.rs @@ -6,7 +6,7 @@ fn foo1(_: &dyn Drop + AsRef) {} //~ ERROR ambiguous `+` in a type fn foo2(_: &dyn (Drop + AsRef)) {} //~ ERROR incorrect braces around trait bounds fn foo3(_: &dyn {Drop + AsRef}) {} //~ ERROR expected parameter name, found `{` -//~^ ERROR expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found `{` +//~^ ERROR expected one of `!`, `(`, `)`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` //~| ERROR at least one trait is required for an object type fn foo4(_: &dyn >) {} //~ ERROR expected identifier, found `<` diff --git a/src/test/ui/parser/trait-object-delimiters.stderr b/src/test/ui/parser/trait-object-delimiters.stderr index 1ae0205615cb1..ee638d8a4f5ec 100644 --- a/src/test/ui/parser/trait-object-delimiters.stderr +++ b/src/test/ui/parser/trait-object-delimiters.stderr @@ -22,11 +22,11 @@ error: expected parameter name, found `{` LL | fn foo3(_: &dyn {Drop + AsRef}) {} | ^ expected parameter name -error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found `{` +error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` --> $DIR/trait-object-delimiters.rs:8:17 | LL | fn foo3(_: &dyn {Drop + AsRef}) {} - | -^ expected one of 8 possible tokens + | -^ expected one of 9 possible tokens | | | help: missing `,` diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 1dbd000afd73e..228b5ed71e80a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,7 +1,5 @@ // FIXME(fee1-dead): this should have a better error message #![feature(const_trait_impl)] -#![feature(const_trait_bound_opt_out)] -#![allow(incomplete_features)] struct NonConstAdd(i32); @@ -14,7 +12,7 @@ impl std::ops::Add for NonConstAdd { } trait Foo { - type Bar: std::ops::Add; + type Bar: ~const std::ops::Add; } impl const Foo for NonConstAdd { @@ -23,7 +21,7 @@ impl const Foo for NonConstAdd { } trait Baz { - type Qux: ?const std::ops::Add; + type Qux: std::ops::Add; } impl const Baz for NonConstAdd { diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index ada29ba3f8b4e..b894092205e43 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,15 +1,15 @@ error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` - --> $DIR/assoc-type.rs:21:5 + --> $DIR/assoc-type.rs:19:5 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` | = help: the trait `Add` is not implemented for `NonConstAdd` note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:17:15 + --> $DIR/assoc-type.rs:15:15 | -LL | type Bar: std::ops::Add; - | ^^^^^^^^^^^^^ required by this bound in `Foo::Bar` +LL | type Bar: ~const std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | impl const Foo for NonConstAdd where NonConstAdd: Add { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs index 536c1d7374023..4b706a190e65e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -6,7 +6,7 @@ trait MyPartialEq { fn eq(&self, other: &Self) -> bool; } -impl const MyPartialEq for T { +impl const MyPartialEq for T { fn eq(&self, other: &Self) -> bool { PartialEq::eq(self, other) } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs index f3391aa63468c..adf8d4f9ea565 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -16,11 +16,11 @@ impl const PartialEq for S { } } -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } -const fn equals_self_wrapper(t: &T) -> bool { +const fn equals_self_wrapper(t: &T) -> bool { equals_self(t) } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr index 4b2fc56aaa78a..818c582869631 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/call-generic-method-fail.rs:7:5 + --> $DIR/call-generic-method-fail.rs:5:5 | LL | *t == *t | ^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index 8343974f8c7e7..6881db0aa02c3 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -9,7 +9,7 @@ impl PartialEq for S { } } -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { true } diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index 7cc54e0129a53..9b9bda7c90ec7 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -8,8 +8,8 @@ LL | pub const EQ: bool = equals_self(&S); note: required by a bound in `equals_self` --> $DIR/call-generic-method-nonconst.rs:12:25 | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^^^^ required by this bound in `equals_self` +LL | const fn equals_self(t: &T) -> bool { + | ^^^^^^^^^^^^^^^^ required by this bound in `equals_self` error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs index aee88d6053eee..aa9bd4d824e17 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -16,7 +16,7 @@ impl const PartialEq for S { } } -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr new file mode 100644 index 0000000000000..0a91719e1f15b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/impl-tilde-const-trait.rs:6:6 + | +LL | impl ~const T for S {} + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr index 834f6a409f5b6..8c55627031d1e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -1,5 +1,5 @@ error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:9:12 + --> $DIR/inherent-impl.rs:7:12 | LL | impl const S {} | ----- ^ inherent impl for this type @@ -9,7 +9,7 @@ LL | impl const S {} = note: only trait implementations may be annotated with `const` error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:12:12 + --> $DIR/inherent-impl.rs:10:12 | LL | impl const T {} | ----- ^ inherent impl for this type diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs index a8912705d9458..b4302f3e75fd4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -17,22 +17,13 @@ fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } fn apit_assoc_bound(_: impl IntoIterator) {} //~^ ERROR `~const` is not allowed -fn generic() {} +fn generic() {} //~^ ERROR `~const` is not allowed -fn where_clause() where T: ~const T {} +fn where_clause

() where P: ~const T {} //~^ ERROR `~const` is not allowed -impl ~const T {} -//~^ ERROR `~const` is not allowed - -fn trait_object() -> &'static dyn ~const T { &S } -//~^ ERROR `~const` is not allowed - -fn trait_object_in_apit(_: impl IntoIterator>) {} -//~^ ERROR `~const` is not allowed - -struct S(std::marker::PhantomData); +struct TildeQuestion(std::marker::PhantomData); //~^ ERROR `~const` and `?` are mutually exclusive fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr new file mode 100644 index 0000000000000..b026099f6829b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -0,0 +1,56 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:8:19 + | +LL | fn rpit() -> impl ~const T { S } + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:17 + | +LL | fn apit(_: impl ~const T) {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:14:50 + | +LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:17:48 + | +LL | fn apit_assoc_bound(_: impl IntoIterator) {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:20:15 + | +LL | fn generic() {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:31 + | +LL | fn where_clause

() where P: ~const T {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-invalid-places.rs:26:25 + | +LL | struct TildeQuestion(std::marker::PhantomData); + | ^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + From c75aeaac0bb2af593b9819cfeae6d518617d48cc Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 26 Aug 2021 17:58:28 +0000 Subject: [PATCH 05/10] Fix #88155 --- .../src/transform/check_consts/check.rs | 82 +++++++++++-------- .../rfc-2632-const-trait-impl/issue-88155.rs | 13 +++ .../issue-88155.stderr | 9 ++ 3 files changed, 68 insertions(+), 36 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 0361ddc915d4c..0de6d743a7a79 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -805,6 +805,8 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } }; + let mut nonconst_call_permission = false; + // Attempting to call a trait method? if let Some(trait_id) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); @@ -824,18 +826,44 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { ); let implsrc = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::new(&infcx); - selcx.select(&obligation).unwrap() + let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + selcx.select(&obligation) }); - // If the method is provided via a where-clause that does not use the `?const` - // opt-out, the call is allowed. - if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc { - debug!( - "const_trait_impl: provided {:?} via where-clause in {:?}", - trait_ref, param_env - ); - return; + match implsrc { + Ok(Some(ImplSource::Param(_, hir::Constness::Const))) => { + debug!( + "const_trait_impl: provided {:?} via where-clause in {:?}", + trait_ref, param_env + ); + return; + } + Ok(Some(ImplSource::UserDefined(data))) => { + let callee_name = tcx.item_name(callee); + if let Some(&did) = tcx.associated_item_def_ids(data.impl_def_id).iter().find(|did| tcx.item_name(**did) == callee_name) { + callee = did; + } + } + _ => { + if !tcx.is_const_fn_raw(callee) { + // At this point, it is only legal when the caller is marked with + // #[default_method_body_is_const], and the callee is in the same + // trait. + let callee_trait = tcx.trait_of_item(callee); + if callee_trait.is_some() { + if tcx.has_attr(caller, sym::default_method_body_is_const) { + if tcx.trait_of_item(caller) == callee_trait { + nonconst_call_permission = true; + } + } + } + + if !nonconst_call_permission { + self.check_op(ops::FnCallNonConst); + return; + } + } + } } // Resolve a trait method call to its concrete implementation, which may be in a @@ -875,34 +903,16 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic; if !tcx.is_const_fn_raw(callee) { - let mut permitted = false; - - let callee_trait = tcx.trait_of_item(callee); - if let Some(trait_id) = callee_trait { - if tcx.has_attr(caller, sym::default_method_body_is_const) { - // permit call to non-const fn when caller has default_method_body_is_const.. - if tcx.trait_of_item(caller) == callee_trait { - // ..and caller and callee are in the same trait. - permitted = true; - } - } - if !permitted { - // if trait's impls are all const, permit the call. - let mut const_impls = true; - tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| { - if const_impls { - if let hir::Constness::NotConst = tcx.impl_constness(imp) { - const_impls = false; - } - } - }); - if const_impls { - permitted = true; - } - } + if tcx.trait_of_item(callee).is_some() { + if tcx.has_attr(callee, sym::default_method_body_is_const) { + // To get to here we must have already found a const impl for the + // trait, but for it to still be non-const can be that the impl is + // using default method bodies. + nonconst_call_permission = true; + } } - if !permitted { + if !nonconst_call_permission { self.check_op(ops::FnCallNonConst); return; } diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs new file mode 100644 index 0000000000000..157005bba7b75 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs @@ -0,0 +1,13 @@ +#![feature(const_fn_trait_bound)] +#![feature(const_trait_impl)] + +pub trait A { + fn assoc() -> bool; +} + +pub const fn foo() -> bool { + T::assoc() + //~^ ERROR calls in constant functions are limited +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr new file mode 100644 index 0000000000000..931baac5389e6 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/issue-88155.rs:9:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. From 80e1ee5aeeadf6b1bd5f272a9c94f67ba57d6248 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 27 Aug 2021 05:02:23 +0000 Subject: [PATCH 06/10] Add `ty::BoundConstness` --- compiler/rustc_middle/src/traits/mod.rs | 3 +- compiler/rustc_middle/src/ty/error.rs | 4 +-- compiler/rustc_middle/src/ty/mod.rs | 35 +++++++++++++----- compiler/rustc_middle/src/ty/relate.rs | 8 ++--- .../rustc_middle/src/ty/structural_impls.rs | 6 ++-- compiler/rustc_middle/src/ty/sty.rs | 2 +- .../src/borrow_check/type_check/canonical.rs | 3 +- .../src/transform/check_consts/check.rs | 4 +-- .../src/traits/auto_trait.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/select/confirmation.rs | 5 ++- .../src/traits/select/mod.rs | 36 ++++++++++--------- compiler/rustc_typeck/src/astconv/mod.rs | 17 ++++----- compiler/rustc_typeck/src/bounds.rs | 3 +- .../rustc_typeck/src/check/fn_ctxt/mod.rs | 4 --- compiler/rustc_typeck/src/collect.rs | 19 ++++------ .../src/impl_wf_check/min_specialization.rs | 5 ++- compiler/rustc_typeck/src/lib.rs | 2 +- 18 files changed, 80 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 457e80c1663ac..676cb7fe41d97 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -17,7 +17,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::Constness; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; @@ -497,7 +496,7 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec, Constness), + Param(Vec, ty::BoundConstness), /// Virtual calls through an object. Object(ImplSourceObjectData<'tcx, N>), diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index ecbe9ca417593..796ca650bdd77 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -33,7 +33,7 @@ impl ExpectedFound { #[derive(Clone, Debug, TypeFoldable)] pub enum TypeError<'tcx> { Mismatch, - ConstnessMismatch(ExpectedFound), + ConstnessMismatch(ExpectedFound), UnsafetyMismatch(ExpectedFound), AbiMismatch(ExpectedFound), Mutability, @@ -102,7 +102,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { CyclicConst(_) => write!(f, "encountered a self-referencing constant"), Mismatch => write!(f, "types differ"), ConstnessMismatch(values) => { - write!(f, "expected {} fn, found {} fn", values.expected, values.found) + write!(f, "expected {} bound, found {} bound", values.expected, values.found) } UnsafetyMismatch(values) => { write!(f, "expected {} fn, found {} fn", values.expected, values.found) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c8ca08f9762b2..8aa27d4ca53e3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -37,7 +37,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX}; -use rustc_hir::{Constness, Node}; +use rustc_hir::Node; use rustc_macros::HashStable; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; @@ -181,6 +181,25 @@ pub enum Visibility { Invisible, } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +pub enum BoundConstness { + /// `T: Trait` + NotConst, + /// `T: ~const Trait` + /// + /// Requires resolving to const only when we are in a const context. + ConstIfConst, +} + +impl fmt::Display for BoundConstness { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NotConst => f.write_str("normal"), + Self::ConstIfConst => f.write_str("`~const`"), + } + } +} + #[derive( Clone, Debug, @@ -628,9 +647,7 @@ impl<'tcx> Predicate<'tcx> { pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, - /// A trait predicate will have `Constness::Const` if it originates - /// from a bound marked with `~const`. - pub constness: hir::Constness, + pub constness: BoundConstness, } pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; @@ -1299,7 +1316,7 @@ impl<'tcx> ParamEnv<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ConstnessAnd { - pub constness: Constness, + pub constness: BoundConstness, pub value: T, } @@ -1307,18 +1324,18 @@ pub struct ConstnessAnd { // the constness of trait bounds is being propagated correctly. pub trait WithConstness: Sized { #[inline] - fn with_constness(self, constness: Constness) -> ConstnessAnd { + fn with_constness(self, constness: BoundConstness) -> ConstnessAnd { ConstnessAnd { constness, value: self } } #[inline] - fn with_const(self) -> ConstnessAnd { - self.with_constness(Constness::Const) + fn with_const_if_const(self) -> ConstnessAnd { + self.with_constness(BoundConstness::ConstIfConst) } #[inline] fn without_const(self) -> ConstnessAnd { - self.with_constness(Constness::NotConst) + self.with_constness(BoundConstness::NotConst) } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 4a2c8349fdc68..44981f171d50a 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -200,12 +200,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { } } -impl<'tcx> Relate<'tcx> for ast::Constness { +impl<'tcx> Relate<'tcx> for ty::BoundConstness { fn relate>( relation: &mut R, - a: ast::Constness, - b: ast::Constness, - ) -> RelateResult<'tcx, ast::Constness> { + a: ty::BoundConstness, + b: ty::BoundConstness, + ) -> RelateResult<'tcx, ty::BoundConstness> { if a != b { Err(TypeError::ConstnessMismatch(expected_found(relation, a, b))) } else { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2ab25c839704d..89ad99d9f0794 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,7 +8,6 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; -use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; @@ -155,8 +154,8 @@ impl fmt::Debug for ty::ParamConst { impl fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let hir::Constness::Const = self.constness { - write!(f, "const ")?; + if let ty::BoundConstness::ConstIfConst = self.constness { + write!(f, "~const ")?; } write!(f, "TraitPredicate({:?})", self.trait_ref) } @@ -241,6 +240,7 @@ TrivialTypeFoldableAndLiftImpls! { crate::traits::Reveal, crate::ty::adjustment::AutoBorrowMutability, crate::ty::AdtKind, + crate::ty::BoundConstness, // Including `BoundRegionKind` is a *bit* dubious, but direct // references to bound region appear in `ty::Error`, and aren't // really meant to be folded. In general, we can only fold a fully diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8b893b779c0a2..65dd61b63295c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -878,7 +878,7 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref, - constness: hir::Constness::NotConst, + constness: ty::BoundConstness::NotConst, }) } } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs b/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs index 9fafcfafe67cd..b501716a89975 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs @@ -1,6 +1,5 @@ use std::fmt; -use rustc_hir as hir; use rustc_infer::infer::canonical::Canonical; use rustc_infer::traits::query::NoSolution; use rustc_middle::mir::ConstraintCategory; @@ -88,7 +87,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.prove_predicates( Some(ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, - constness: hir::Constness::NotConst, + constness: ty::BoundConstness::NotConst, })), locations, category, diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 0de6d743a7a79..944b5ca898603 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -821,7 +821,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { param_env, Binder::dummy(TraitPredicate { trait_ref, - constness: hir::Constness::Const, + constness: ty::BoundConstness::ConstIfConst, }), ); @@ -831,7 +831,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { }); match implsrc { - Ok(Some(ImplSource::Param(_, hir::Constness::Const))) => { + Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => { debug!( "const_trait_impl: provided {:?} via where-clause in {:?}", trait_ref, param_env diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 282502cfa0d3d..622c9edc43450 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -285,7 +285,7 @@ impl AutoTraitFinder<'tcx> { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), }, - constness: hir::Constness::NotConst, + constness: ty::BoundConstness::NotConst, })); let computed_preds = param_env.caller_bounds().iter(); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 554b2950263ec..cec07281d2abd 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -778,7 +778,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot( let obligation = Obligation::new( ObligationCause::dummy(), ty::ParamEnv::reveal_all(), - ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: hir::Constness::NotConst }), + ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c571a1d628427..6fae8173985be 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,7 +8,6 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; @@ -75,7 +74,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ProjectionCandidate(idx) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; // FIXME(jschievink): constness - Ok(ImplSource::Param(obligations, Constness::NotConst)) + Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst)) } ObjectCandidate(idx) => { @@ -113,7 +112,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - Ok(ImplSource::Param(Vec::new(), Constness::NotConst)) + Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)) } BuiltinUnsizeCandidate => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1580562a92f38..40e413847e037 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,7 +32,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::Constness; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; @@ -130,8 +129,8 @@ pub struct SelectionContext<'cx, 'tcx> { /// and a negative impl allow_negative_impls: bool, - /// Do we only want const impls when we have a const trait predicate? - const_impls_required: bool, + /// Are we in a const context that needs `~const` bounds to be const? + is_in_const_context: bool, /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated @@ -224,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - const_impls_required: false, + is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -236,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, - const_impls_required: false, + is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -252,7 +251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, - const_impls_required: false, + is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -268,7 +267,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - const_impls_required: false, + is_in_const_context: false, query_mode, } } @@ -283,7 +282,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - const_impls_required: matches!(constness, hir::Constness::Const), + is_in_const_context: matches!(constness, hir::Constness::Const), query_mode: TraitQueryMode::Standard, } } @@ -316,14 +315,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.tcx } + /// Returns `true` if the trait predicate is considerd `const` to this selection context. + pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { + match pred.constness { + ty::BoundConstness::ConstIfConst if self.is_in_const_context => true, + _ => false + } + } + /// Returns `true` if the predicate is considered `const` to /// this selection context. pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool { match pred.kind().skip_binder() { - ty::PredicateKind::Trait(ty::TraitPredicate { - constness: hir::Constness::Const, - .. - }) if self.const_impls_required => true, + ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred), _ => false, } } @@ -1074,8 +1078,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Respect const trait obligations - if self.const_impls_required { - if let hir::Constness::Const = obligation.predicate.skip_binder().constness { + if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { if Some(obligation.predicate.skip_binder().trait_ref.def_id) != tcx.lang_items().sized_trait() // const Sized bounds are skipped @@ -1086,7 +1089,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if tcx.impl_constness(def_id) == hir::Constness::Const => {} // const param ParamCandidate(ty::ConstnessAnd { - constness: hir::Constness::Const, + constness: ty::BoundConstness::ConstIfConst, .. }) => {} // auto trait impl @@ -1100,7 +1103,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } - } } // Treat negative impls as unimplemented, and reservation impls as ambiguity. if let ImplCandidate(def_id) = candidate { @@ -1495,7 +1497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. other.value.bound_vars().len() <= victim.value.bound_vars().len() - } else if other.value == victim.value && victim.constness == Constness::NotConst { + } else if other.value == victim.value && victim.constness == ty::BoundConstness::NotConst { // Drop otherwise equivalent non-const candidates in favor of const candidates. true } else { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index b7054d1562686..059e0cadd190c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -20,7 +20,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Constness, GenericArg, GenericArgs}; +use rustc_hir::{GenericArg, GenericArgs}; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable}; @@ -47,8 +47,6 @@ pub trait AstConv<'tcx> { fn item_def_id(&self) -> Option; - fn default_constness_for_trait_bounds(&self) -> Constness; - /// Returns predicates in scope of the form `X: Foo`, where `X` /// is a type parameter `X` with the given id `def_id` and T /// matches `assoc_name`. This is a subset of the full set of @@ -724,7 +722,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, trait_ref: &hir::TraitRef<'_>, span: Span, - constness: Constness, + constness: ty::BoundConstness, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, @@ -795,7 +793,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bound_vars = tcx.late_bound_vars(hir_id); let poly_trait_ref = ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); - bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst)); + bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst)); let mut dup_bindings = FxHashMap::default(); for binding in assoc_bindings { @@ -920,14 +918,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, ) { - let constness = self.default_constness_for_trait_bounds(); for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { self.instantiate_poly_trait_ref( &b.trait_ref, b.span, - Constness::NotConst, + ty::BoundConstness::NotConst, param_ty, bounds, false, @@ -937,7 +934,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.instantiate_poly_trait_ref( &b.trait_ref, b.span, - constness, + ty::BoundConstness::ConstIfConst, param_ty, bounds, false, @@ -1251,7 +1248,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } = self.instantiate_poly_trait_ref( &trait_bound.trait_ref, trait_bound.span, - Constness::NotConst, + ty::BoundConstness::NotConst, dummy_self, &mut bounds, false, @@ -1330,7 +1327,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, Constness::NotConst); + assert_eq!(constness, ty::BoundConstness::NotConst); for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) { debug!( diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 5d20064072263..24474e163b9da 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -1,7 +1,6 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. -use rustc_hir::Constness; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_span::Span; @@ -30,7 +29,7 @@ pub struct Bounds<'tcx> { /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. - pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>, + pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>, /// A list of projection equality bounds. So if you had `T: /// Iterator` this would include ` AstConv<'tcx> for FnCtxt<'a, 'tcx> { None } - fn default_constness_for_trait_bounds(&self) -> hir::Constness { - self.tcx.hir().get(self.body_id).constness_for_typeck() - } - fn get_type_parameter_bounds( &self, _: Span, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 3ae26c3eb78e0..f0f7f15a0a6cb 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -365,10 +365,6 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { Some(self.item_def_id) } - fn default_constness_for_trait_bounds(&self) -> hir::Constness { - self.node().constness_for_typeck() - } - fn get_type_parameter_bounds( &self, span: Span, @@ -664,7 +660,6 @@ impl ItemCtxt<'tcx> { only_self_bounds: OnlySelfBounds, assoc_name: Option, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - let constness = self.default_constness_for_trait_bounds(); let from_ty_params = ast_generics .params .iter() @@ -677,7 +672,7 @@ impl ItemCtxt<'tcx> { Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), None => true, }) - .flat_map(|b| predicates_from_bound(self, ty, b, constness)); + .flat_map(|b| predicates_from_bound(self, ty, b)); let from_where_clauses = ast_generics .where_clause @@ -703,7 +698,7 @@ impl ItemCtxt<'tcx> { }) .filter_map(move |b| bt.map(|bt| (bt, b))) }) - .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness)); + .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); from_ty_params.chain(from_where_clauses).collect() } @@ -2031,7 +2026,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let mut is_default_impl_trait = None; let icx = ItemCtxt::new(tcx, def_id); - let constness = icx.default_constness_for_trait_bounds(); const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty(); @@ -2227,8 +2221,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { let constness = match modifier { - hir::TraitBoundModifier::None => hir::Constness::NotConst, - hir::TraitBoundModifier::MaybeConst => constness, + hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, + hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, // We ignore `where T: ?Sized`, it is already part of // type parameter `T`. hir::TraitBoundModifier::Maybe => continue, @@ -2491,14 +2485,13 @@ fn predicates_from_bound<'tcx>( astconv: &dyn AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, - constness: hir::Constness, ) -> Vec<(ty::Predicate<'tcx>, Span)> { match *bound { hir::GenericBound::Trait(ref tr, modifier) => { let constness = match modifier { hir::TraitBoundModifier::Maybe => return vec![], - hir::TraitBoundModifier::MaybeConst => constness, - hir::TraitBoundModifier::None => hir::Constness::NotConst, + hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, + hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, }; let mut bounds = Bounds::default(); diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index d3e4be128a8df..8ecd6034ad695 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -68,7 +68,6 @@ use crate::constrained_generic_params as cgp; use rustc_data_structures::fx::FxHashSet; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; @@ -368,7 +367,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc // items. ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, - constness: hir::Constness::NotConst, + constness: ty::BoundConstness::NotConst, }) => { if !matches!( trait_predicate_kind(tcx, predicate), @@ -399,7 +398,7 @@ fn trait_predicate_kind<'tcx>( match predicate.kind().skip_binder() { ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, - constness: hir::Constness::NotConst, + constness: ty::BoundConstness::NotConst, }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::PredicateKind::Trait(_) | ty::PredicateKind::RegionOutlives(_) diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 638a46fec36f4..749f681e92ed1 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -548,7 +548,7 @@ pub fn hir_trait_to_predicates<'tcx>( &item_cx, hir_trait, DUMMY_SP, - hir::Constness::NotConst, + ty::BoundConstness::NotConst, self_ty, &mut bounds, true, From 580ca930ac6423dd1dc6a1d90f9d899c8fb5e562 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 27 Aug 2021 07:12:40 +0000 Subject: [PATCH 07/10] Fix UI test --- .../call-generic-method-dup-bound.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index 5853b66b868a5..7185376b440c8 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -16,7 +16,9 @@ impl const PartialEq for S { // This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const // bound. -const fn equals_self(t: &T) -> bool { +// const fn equals_self(t: &T) -> bool { +// FIXME(fee1-dead)^ why should the order matter here? +const fn equals_self(t: &T) -> bool { *t == *t } From f3d96e939185e1fd35f80a25656bb8c53a0885b9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 27 Aug 2021 08:09:00 +0000 Subject: [PATCH 08/10] fmt --- .../src/transform/check_consts/check.rs | 13 +++-- .../rustc_trait_selection/src/traits/mod.rs | 5 +- .../src/traits/select/mod.rs | 50 ++++++++++--------- compiler/rustc_typeck/src/collect.rs | 4 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 944b5ca898603..2b748062cdf23 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -826,7 +826,8 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { ); let implsrc = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = + SelectionContext::with_constness(&infcx, hir::Constness::Const); selcx.select(&obligation) }); @@ -834,13 +835,17 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => { debug!( "const_trait_impl: provided {:?} via where-clause in {:?}", - trait_ref, param_env + trait_ref, param_env ); return; } Ok(Some(ImplSource::UserDefined(data))) => { let callee_name = tcx.item_name(callee); - if let Some(&did) = tcx.associated_item_def_ids(data.impl_def_id).iter().find(|did| tcx.item_name(**did) == callee_name) { + if let Some(&did) = tcx + .associated_item_def_ids(data.impl_def_id) + .iter() + .find(|did| tcx.item_name(**did) == callee_name) + { callee = did; } } @@ -909,7 +914,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { // trait, but for it to still be non-const can be that the impl is // using default method bodies. nonconst_call_permission = true; - } + } } if !nonconst_call_permission { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index cec07281d2abd..17a4184c3c9ef 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -778,7 +778,10 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot( let obligation = Obligation::new( ObligationCause::dummy(), ty::ParamEnv::reveal_all(), - ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst }), + ty::Binder::dummy(ty::TraitPredicate { + trait_ref, + constness: ty::BoundConstness::NotConst, + }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 40e413847e037..6cf1dabad8592 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -319,7 +319,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { match pred.constness { ty::BoundConstness::ConstIfConst if self.is_in_const_context => true, - _ => false + _ => false, } } @@ -1079,30 +1079,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); // Respect const trait obligations if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { - if Some(obligation.predicate.skip_binder().trait_ref.def_id) - != tcx.lang_items().sized_trait() - // const Sized bounds are skipped - { - match candidate { - // const impl - ImplCandidate(def_id) - if tcx.impl_constness(def_id) == hir::Constness::Const => {} - // const param - ParamCandidate(ty::ConstnessAnd { - constness: ty::BoundConstness::ConstIfConst, - .. - }) => {} - // auto trait impl - AutoImplCandidate(..) => {} - // generator, this will raise error in other places - // or ignore error with const_async_blocks feature - GeneratorCandidate => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); - } + if Some(obligation.predicate.skip_binder().trait_ref.def_id) + != tcx.lang_items().sized_trait() + // const Sized bounds are skipped + { + match candidate { + // const impl + ImplCandidate(def_id) + if tcx.impl_constness(def_id) == hir::Constness::Const => {} + // const param + ParamCandidate(ty::ConstnessAnd { + constness: ty::BoundConstness::ConstIfConst, + .. + }) => {} + // auto trait impl + AutoImplCandidate(..) => {} + // generator, this will raise error in other places + // or ignore error with const_async_blocks feature + GeneratorCandidate => {} + _ => { + // reject all other types of candidates + return Err(Unimplemented); } } + } } // Treat negative impls as unimplemented, and reservation impls as ambiguity. if let ImplCandidate(def_id) = candidate { @@ -1497,7 +1497,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. other.value.bound_vars().len() <= victim.value.bound_vars().len() - } else if other.value == victim.value && victim.constness == ty::BoundConstness::NotConst { + } else if other.value == victim.value + && victim.constness == ty::BoundConstness::NotConst + { // Drop otherwise equivalent non-const candidates in favor of const candidates. true } else { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index f0f7f15a0a6cb..b514176ad529d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2222,7 +2222,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP hir::GenericBound::Trait(poly_trait_ref, modifier) => { let constness = match modifier { hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, - hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, + hir::TraitBoundModifier::MaybeConst => { + ty::BoundConstness::ConstIfConst + } // We ignore `where T: ?Sized`, it is already part of // type parameter `T`. hir::TraitBoundModifier::Maybe => continue, From 0a3a6087fb91d185700d18b13365ad5969c97eb9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 27 Aug 2021 08:26:35 +0000 Subject: [PATCH 09/10] Revive tests --- src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs | 6 ++++++ src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr | 8 ++++++++ src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs | 6 ++++++ .../ui/rfc-2632-const-trait-impl/without-tilde.stderr | 8 ++++++++ 4 files changed, 28 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs new file mode 100644 index 0000000000000..06e4ede8b5e7e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S; +//~^ ERROR expected identifier, found `~` diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr new file mode 100644 index 0000000000000..928d23e8a424d --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `~` + --> $DIR/tilde-twice.rs:5:20 + | +LL | struct S; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs new file mode 100644 index 0000000000000..96ba393bd8594 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs @@ -0,0 +1,6 @@ +// compiler-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S; +//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr new file mode 100644 index 0000000000000..b6b77ac4a2fb6 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const` + --> $DIR/without-tilde.rs:5:13 + | +LL | struct S; + | ^^^^^ expected one of 10 possible tokens + +error: aborting due to previous error + From 2d7dbf2e05284aba0a99c40db007c512631872ca Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 27 Aug 2021 11:53:03 +0000 Subject: [PATCH 10/10] Fix rustfmt test --- src/tools/rustfmt/tests/source/type.rs | 24 +++++++++--------------- src/tools/rustfmt/tests/target/type.rs | 6 ------ 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/tools/rustfmt/tests/source/type.rs b/src/tools/rustfmt/tests/source/type.rs index 57f31dc901e77..61ef73a3cab1c 100644 --- a/src/tools/rustfmt/tests/source/type.rs +++ b/src/tools/rustfmt/tests/source/type.rs @@ -140,29 +140,23 @@ fn foo(a: SomeLongComplexType, b: SomeOtherLongComplexType) -> Box Box>; -// Const opt-out +// Const bound -trait T: ? const Super {} +trait T: ~ const Super {} -const fn maybe_const() -> i32 { ::CONST } +const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); +struct S(std::marker::PhantomData); -impl ? const T {} +impl ~ const T {} -fn trait_object() -> &'static dyn ? const T { &S } +fn apit(_: impl ~ const T) {} -fn i(_: impl IntoIterator>) {} - -fn apit(_: impl ?const T) {} - -fn rpit() -> impl ? const T { S } +fn rpit() -> impl ~ const T { S } pub struct Foo(T); -impl Foo { +impl Foo { fn new(t: T) -> Self { - // not calling methods on `t`, so we opt out of requiring - // `` to have const methods via `?const` Self(t) } } @@ -171,4 +165,4 @@ impl Foo { type T = typeof( 1); impl T for .. { -} \ No newline at end of file +} diff --git a/src/tools/rustfmt/tests/target/type.rs b/src/tools/rustfmt/tests/target/type.rs index 9ab66944c8ccc..38cf909c2587a 100644 --- a/src/tools/rustfmt/tests/target/type.rs +++ b/src/tools/rustfmt/tests/target/type.rs @@ -157,12 +157,6 @@ struct S(std::marker::PhantomData); impl ~const T {} -fn trait_object() -> &'static dyn ~const T { - &S -} - -fn i(_: impl IntoIterator>) {} - fn apit(_: impl ~const T) {} fn rpit() -> impl ~const T {