Skip to content

Commit af4572d

Browse files
committed
Auto merge of rust-lang#119243 - matthiaskrgr:rollup-xszboqi, r=matthiaskrgr
Rollup of 2 pull requests Successful merges: - rust-lang#119072 (Clean up `check_consts` and misc fixes) - rust-lang#119231 (Clairify `ast::PatKind::Struct` presese of `..` by using an enum instead of a bool) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c03d978 + ddbc1cf commit af4572d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+206
-314
lines changed

compiler/rustc_ast/src/ast.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,7 @@ pub enum PatKind {
754754
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
755755

756756
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
757-
/// The `bool` is `true` in the presence of a `..`.
758-
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool),
757+
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
759758

760759
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
761760
TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
@@ -812,6 +811,15 @@ pub enum PatKind {
812811
MacCall(P<MacCall>),
813812
}
814813

814+
/// Whether the `..` is present in a struct fields pattern.
815+
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
816+
pub enum PatFieldsRest {
817+
/// `module::StructName { field, ..}`
818+
Rest,
819+
/// `module::StructName { field }`
820+
None,
821+
}
822+
815823
/// The kind of borrow in an `AddrOf` expression,
816824
/// e.g., `&place` or `&raw const place`.
817825
#[derive(Clone, Copy, PartialEq, Eq, Debug)]

compiler/rustc_ast_lowering/src/pat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
8282
span: self.lower_span(f.span),
8383
}
8484
}));
85-
break hir::PatKind::Struct(qpath, fs, *etc);
85+
break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest);
8686
}
8787
PatKind::Tuple(pats) => {
8888
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");

compiler/rustc_ast_pretty/src/pprust/state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@ impl<'a> State<'a> {
14271427
}
14281428
self.nbsp();
14291429
self.word("{");
1430-
let empty = fields.is_empty() && !etc;
1430+
let empty = fields.is_empty() && *etc == ast::PatFieldsRest::None;
14311431
if !empty {
14321432
self.space();
14331433
}
@@ -1445,7 +1445,7 @@ impl<'a> State<'a> {
14451445
},
14461446
|f| f.pat.span,
14471447
);
1448-
if *etc {
1448+
if *etc == ast::PatFieldsRest::Rest {
14491449
if !fields.is_empty() {
14501450
self.word_space(",");
14511451
}

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+40-147
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_index::bit_set::BitSet;
77
use rustc_infer::infer::TyCtxtInferExt;
8-
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
8+
use rustc_infer::traits::ObligationCause;
99
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
1010
use rustc_middle::mir::*;
11-
use rustc_middle::traits::BuiltinImplSource;
12-
use rustc_middle::ty::GenericArgs;
13-
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
14-
use rustc_middle::ty::{TraitRef, TypeVisitableExt};
11+
use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
12+
use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt};
1513
use rustc_mir_dataflow::Analysis;
1614
use rustc_span::{sym, Span, Symbol};
1715
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
18-
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
16+
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
1917
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
2018

2119
use std::mem;
@@ -756,143 +754,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
756754
infcx.err_ctxt().report_fulfillment_errors(errors);
757755
}
758756

757+
let mut is_trait = false;
759758
// Attempting to call a trait method?
760-
// FIXME(effects) do we need this?
761-
if let Some(trait_id) = tcx.trait_of_item(callee) {
759+
if tcx.trait_of_item(callee).is_some() {
762760
trace!("attempting to call a trait method");
763-
if !self.tcx.features().const_trait_impl {
761+
// trait method calls are only permitted when `effects` is enabled.
762+
// we don't error, since that is handled by typeck. We try to resolve
763+
// the trait into the concrete method, and uses that for const stability
764+
// checks.
765+
// FIXME(effects) we might consider moving const stability checks to typeck as well.
766+
if tcx.features().effects {
767+
is_trait = true;
768+
769+
if let Ok(Some(instance)) =
770+
Instance::resolve(tcx, param_env, callee, fn_args)
771+
&& let InstanceDef::Item(def) = instance.def
772+
{
773+
// Resolve a trait method call to its concrete implementation, which may be in a
774+
// `const` trait impl. This is only used for the const stability check below, since
775+
// we want to look at the concrete impl's stability.
776+
fn_args = instance.args;
777+
callee = def;
778+
}
779+
} else {
764780
self.check_op(ops::FnCallNonConst {
765781
caller,
766782
callee,
767783
args: fn_args,
768784
span: *fn_span,
769785
call_source: *call_source,
770-
feature: Some(sym::const_trait_impl),
786+
feature: Some(if tcx.features().const_trait_impl {
787+
sym::effects
788+
} else {
789+
sym::const_trait_impl
790+
}),
771791
});
772792
return;
773793
}
774-
775-
let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
776-
let obligation =
777-
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
778-
779-
let implsrc = {
780-
let infcx = tcx.infer_ctxt().build();
781-
let mut selcx = SelectionContext::new(&infcx);
782-
selcx.select(&obligation)
783-
};
784-
785-
match implsrc {
786-
Ok(Some(ImplSource::Param(_))) if tcx.features().effects => {
787-
debug!(
788-
"const_trait_impl: provided {:?} via where-clause in {:?}",
789-
trait_ref, param_env
790-
);
791-
return;
792-
}
793-
// Closure: Fn{Once|Mut}
794-
Ok(Some(ImplSource::Builtin(BuiltinImplSource::Misc, _)))
795-
if trait_ref.self_ty().is_closure()
796-
&& tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
797-
{
798-
let ty::Closure(closure_def_id, fn_args) = *trait_ref.self_ty().kind()
799-
else {
800-
unreachable!()
801-
};
802-
if !tcx.is_const_fn_raw(closure_def_id) {
803-
self.check_op(ops::FnCallNonConst {
804-
caller,
805-
callee,
806-
args: fn_args,
807-
span: *fn_span,
808-
call_source: *call_source,
809-
feature: None,
810-
});
811-
812-
return;
813-
}
814-
}
815-
Ok(Some(ImplSource::UserDefined(data))) => {
816-
let callee_name = tcx.item_name(callee);
817-
818-
if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) {
819-
self.check_op(ops::FnCallNonConst {
820-
caller,
821-
callee,
822-
args: fn_args,
823-
span: *fn_span,
824-
call_source: *call_source,
825-
feature: None,
826-
});
827-
return;
828-
}
829-
830-
if let Some(&did) = tcx
831-
.associated_item_def_ids(data.impl_def_id)
832-
.iter()
833-
.find(|did| tcx.item_name(**did) == callee_name)
834-
{
835-
// using internal args is ok here, since this is only
836-
// used for the `resolve` call below
837-
fn_args = GenericArgs::identity_for_item(tcx, did);
838-
callee = did;
839-
}
840-
}
841-
_ if !tcx.is_const_fn_raw(callee) => {
842-
// At this point, it is only legal when the caller is in a trait
843-
// marked with #[const_trait], and the callee is in the same trait.
844-
let mut nonconst_call_permission = false;
845-
if let Some(callee_trait) = tcx.trait_of_item(callee)
846-
&& tcx.has_attr(callee_trait, sym::const_trait)
847-
&& Some(callee_trait) == tcx.trait_of_item(caller.to_def_id())
848-
// Can only call methods when it's `<Self as TheTrait>::f`.
849-
&& tcx.types.self_param == fn_args.type_at(0)
850-
{
851-
nonconst_call_permission = true;
852-
}
853-
854-
if !nonconst_call_permission {
855-
let obligation = Obligation::new(
856-
tcx,
857-
ObligationCause::dummy_with_span(*fn_span),
858-
param_env,
859-
trait_ref,
860-
);
861-
862-
// improve diagnostics by showing what failed. Our requirements are stricter this time
863-
// as we are going to error again anyways.
864-
let infcx = tcx.infer_ctxt().build();
865-
if let Err(e) = implsrc {
866-
infcx.err_ctxt().report_selection_error(
867-
obligation.clone(),
868-
&obligation,
869-
&e,
870-
);
871-
}
872-
873-
self.check_op(ops::FnCallNonConst {
874-
caller,
875-
callee,
876-
args: fn_args,
877-
span: *fn_span,
878-
call_source: *call_source,
879-
feature: None,
880-
});
881-
return;
882-
}
883-
}
884-
_ => {}
885-
}
886-
887-
// Resolve a trait method call to its concrete implementation, which may be in a
888-
// `const` trait impl.
889-
let instance = Instance::resolve(tcx, param_env, callee, fn_args);
890-
debug!("Resolving ({:?}) -> {:?}", callee, instance);
891-
if let Ok(Some(func)) = instance {
892-
if let InstanceDef::Item(def) = func.def {
893-
callee = def;
894-
}
895-
}
896794
}
897795

898796
// At this point, we are calling a function, `callee`, whose `DefId` is known...
@@ -925,21 +823,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
925823
return;
926824
}
927825

928-
if !tcx.is_const_fn_raw(callee) {
929-
if !tcx.is_const_default_method(callee) {
930-
// To get to here we must have already found a const impl for the
931-
// trait, but for it to still be non-const can be that the impl is
932-
// using default method bodies.
933-
self.check_op(ops::FnCallNonConst {
934-
caller,
935-
callee,
936-
args: fn_args,
937-
span: *fn_span,
938-
call_source: *call_source,
939-
feature: None,
940-
});
941-
return;
942-
}
826+
if !tcx.is_const_fn_raw(callee) && !is_trait {
827+
self.check_op(ops::FnCallNonConst {
828+
caller,
829+
callee,
830+
args: fn_args,
831+
span: *fn_span,
832+
call_source: *call_source,
833+
feature: None,
834+
});
835+
return;
943836
}
944837

945838
// If the `const fn` we are trying to call is not const-stable, ensure that we have

compiler/rustc_expand/src/build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ impl<'a> ExtCtxt<'a> {
491491
path: ast::Path,
492492
field_pats: ThinVec<ast::PatField>,
493493
) -> P<ast::Pat> {
494-
self.pat(span, PatKind::Struct(None, path, field_pats, false))
494+
self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
495495
}
496496
pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
497497
self.pat(span, PatKind::Tuple(pats))

compiler/rustc_hir_analysis/src/astconv/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
378378
assert!(self_ty.is_none());
379379
}
380380

381-
let arg_count = check_generic_arg_count(
381+
let mut arg_count = check_generic_arg_count(
382382
tcx,
383383
span,
384384
def_id,
@@ -560,6 +560,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
560560
inferred_params: vec![],
561561
infer_args,
562562
};
563+
if let ty::BoundConstness::ConstIfConst = constness
564+
&& generics.has_self
565+
&& !tcx.has_attr(def_id, sym::const_trait)
566+
{
567+
let e = tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
568+
arg_count.correct =
569+
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
570+
}
563571
let args = create_args_for_parent_generic_args(
564572
tcx,
565573
def_id,
@@ -570,13 +578,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
570578
&mut args_ctx,
571579
);
572580

573-
if let ty::BoundConstness::ConstIfConst = constness
574-
&& generics.has_self
575-
&& !tcx.has_attr(def_id, sym::const_trait)
576-
{
577-
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
578-
}
579-
580581
(args, arg_count)
581582
}
582583

compiler/rustc_parse/src/parser/pat.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_ast::ptr::P;
1515
use rustc_ast::token::{self, Delimiter};
1616
use rustc_ast::{
1717
self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
18-
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
18+
PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
1919
};
2020
use rustc_ast_pretty::pprust;
2121
use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
@@ -891,7 +891,8 @@ impl<'a> Parser<'a> {
891891
e.span_label(path.span, "while parsing the fields for this pattern");
892892
e.emit();
893893
self.recover_stmt();
894-
(ThinVec::new(), true)
894+
// When recovering, pretend we had `Foo { .. }`, to avoid cascading errors.
895+
(ThinVec::new(), PatFieldsRest::Rest)
895896
});
896897
self.bump();
897898
Ok(PatKind::Struct(qself, path, fields, etc))
@@ -965,9 +966,9 @@ impl<'a> Parser<'a> {
965966
}
966967

967968
/// Parses the fields of a struct-like pattern.
968-
fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, bool)> {
969+
fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> {
969970
let mut fields = ThinVec::new();
970-
let mut etc = false;
971+
let mut etc = PatFieldsRest::None;
971972
let mut ate_comma = true;
972973
let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
973974
let mut first_etc_and_maybe_comma_span = None;
@@ -1001,7 +1002,7 @@ impl<'a> Parser<'a> {
10011002
|| self.check_noexpect(&token::DotDotDot)
10021003
|| self.check_keyword(kw::Underscore)
10031004
{
1004-
etc = true;
1005+
etc = PatFieldsRest::Rest;
10051006
let mut etc_sp = self.token.span;
10061007
if first_etc_and_maybe_comma_span.is_none() {
10071008
if let Some(comma_tok) = self

src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ fn extend_with_struct_pat(
293293
qself1: &Option<P<ast::QSelf>>,
294294
path1: &ast::Path,
295295
fps1: &mut [ast::PatField],
296-
rest1: bool,
296+
rest1: ast::PatFieldsRest,
297297
start: usize,
298298
alternatives: &mut ThinVec<P<Pat>>,
299299
) -> bool {

src/tools/rustfmt/src/patterns.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,15 @@ impl Rewrite for Pat {
259259
None,
260260
None,
261261
),
262-
PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => {
263-
rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape)
264-
}
262+
PatKind::Struct(ref qself, ref path, ref fields, rest) => rewrite_struct_pat(
263+
qself,
264+
path,
265+
fields,
266+
rest == ast::PatFieldsRest::Rest,
267+
self.span,
268+
context,
269+
shape,
270+
),
265271
PatKind::MacCall(ref mac) => {
266272
rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
267273
}

tests/ui/consts/auxiliary/closure-in-foreign-crate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![crate_type = "lib"]
2-
#![feature(const_closures, const_trait_impl)]
2+
#![feature(const_closures, const_trait_impl, effects)]
33
#![allow(incomplete_features)]
44

55
pub const fn test() {

0 commit comments

Comments
 (0)