From 3f17dae37d8829a03312340918a839f0bf8b6088 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Mar 2022 20:28:35 -0800 Subject: [PATCH 1/4] check extra args even if the function is not c_variadic --- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 22 ++++++++++--------- src/test/ui/tuple/wrong_argument_ice-4.rs | 6 +++++ src/test/ui/tuple/wrong_argument_ice-4.stderr | 15 +++++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/tuple/wrong_argument_ice-4.rs create mode 100644 src/test/ui/tuple/wrong_argument_ice-4.stderr diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 3f6247facd1a2..f165093c958db 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -281,6 +281,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty); }; + let minimum_input_count = formal_input_tys.len(); + // Check the arguments. // We do this in a pretty awful way: first we type-check any arguments // that are not closures, then we type-check the closures. This is so @@ -303,7 +305,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } - let minimum_input_count = formal_input_tys.len(); for (idx, arg) in provided_args.iter().enumerate() { // Warn only for the first loop (the "no closures" one). // Closure arguments themselves can't be diverging, but @@ -456,17 +457,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - // We also need to make sure we at least write the ty of the other - // arguments which we skipped above. - if c_variadic { - fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) { - use crate::structured_errors::MissingCastForVariadicArg; + for arg in provided_args.iter().skip(minimum_input_count) { + let arg_ty = self.check_expr(&arg); - MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); - } + if c_variadic { + // We also need to make sure we at least write the ty of the other + // arguments which we skipped above, either because they were additional + // c_variadic args, or because we had an argument count mismatch. + fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) { + use crate::structured_errors::MissingCastForVariadicArg; - for arg in provided_args.iter().skip(expected_arg_count) { - let arg_ty = self.check_expr(&arg); + MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit(); + } // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. diff --git a/src/test/ui/tuple/wrong_argument_ice-4.rs b/src/test/ui/tuple/wrong_argument_ice-4.rs new file mode 100644 index 0000000000000..479bd0d819fdb --- /dev/null +++ b/src/test/ui/tuple/wrong_argument_ice-4.rs @@ -0,0 +1,6 @@ +fn main() { + (|| {})(|| { + //~^ ERROR this function takes 0 arguments but 1 argument was supplied + let b = 1; + }); +} diff --git a/src/test/ui/tuple/wrong_argument_ice-4.stderr b/src/test/ui/tuple/wrong_argument_ice-4.stderr new file mode 100644 index 0000000000000..fef5dca856db3 --- /dev/null +++ b/src/test/ui/tuple/wrong_argument_ice-4.stderr @@ -0,0 +1,15 @@ +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/wrong_argument_ice-4.rs:2:5 + | +LL | (|| {})(|| { + | _____^^^^^^^_- + | | | + | | expected 0 arguments +LL | | +LL | | let b = 1; +LL | | }); + | |_____- supplied 1 argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. From 51a53bf4df0fa2717c0c0a81c14cbc2192d377b7 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 7 Mar 2022 02:18:36 +0900 Subject: [PATCH 2/4] remove unnecessary `..` patterns --- compiler/rustc_ast_lowering/src/lib.rs | 8 ++------ compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 940887280b9c1..7a272308fb051 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2064,17 +2064,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { )), _ => None, }); - if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } = - itctx - { + if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes } = itctx { capturable_lifetimes.extend(lt_def_names.clone()); } let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow()); - if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } = - itctx - { + if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes } = itctx { for param in lt_def_names { capturable_lifetimes.remove(¶m); } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6886a0f4cf148..d84a96e40fb01 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -657,7 +657,7 @@ pub fn write_allocations<'tcx>( } fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator + '_ { match val { - ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => { + ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => { Either::Left(Either::Left(std::iter::once(ptr.provenance))) } ConstValue::Scalar(interpret::Scalar::Int { .. }) => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b56cb86a18c86..fd1c0239b5965 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -852,7 +852,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { self.visit(self.ev.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const { has_default, .. } => { + GenericParamDefKind::Const { has_default } => { self.visit(self.ev.tcx.type_of(param.def_id)); if has_default { self.visit(self.ev.tcx.const_param_default(param.def_id)); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b194e6a6d89f3..f2ddc3ea7fa39 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -405,7 +405,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } hir::Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, generics, _, _) + hir::ItemKind::Trait(_, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }), .. }) if projection.is_some() => { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index e46eccd61b14c..b3213451d76c4 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1403,7 +1403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const { has_default, .. } => { + GenericParamDefKind::Const { has_default } => { if !infer_args && has_default { tcx.const_param_default(param.def_id) .subst_spanned(tcx, substs.unwrap(), Some(self.span)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0d1482ce47017..fcece84b09fb5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -451,7 +451,7 @@ impl Clean for ty::GenericParamDef { }, ) } - ty::GenericParamDefKind::Const { has_default, .. } => ( + ty::GenericParamDefKind::Const { has_default } => ( self.name, GenericParamDefKind::Const { did: self.def_id, From d29d2307b95dcde3c089949d9d4b4c3fdcc2c325 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Mar 2022 14:01:01 -0500 Subject: [PATCH 3/4] CTFE engine: expose misc_cast to Miri --- compiler/rustc_const_eval/src/interpret/cast.rs | 10 +++++----- compiler/rustc_const_eval/src/interpret/operand.rs | 11 ++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index e2c4eb1dadc83..5be0a183cf6b4 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -97,7 +97,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } - fn misc_cast( + pub fn misc_cast( &self, src: &ImmTy<'tcx, M::PointerTag>, cast_ty: Ty<'tcx>, @@ -139,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) { assert!(src.layout.is_zst()); let discr_layout = self.layout_of(discr.ty)?; - return Ok(self.cast_from_scalar(discr.val, discr_layout, cast_ty).into()); + return Ok(self.cast_from_int_like(discr.val, discr_layout, cast_ty).into()); } } Variants::Multiple { .. } => {} @@ -169,17 +169,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - // # The remaining source values are scalar. + // # The remaining source values are scalar and "int-like". // For all remaining casts, we either // (a) cast a raw ptr to usize, or // (b) cast from an integer-like (including bool, char, enums). // In both cases we want the bits. let bits = src.to_scalar()?.to_bits(src.layout.size)?; - Ok(self.cast_from_scalar(bits, src.layout, cast_ty).into()) + Ok(self.cast_from_int_like(bits, src.layout, cast_ty).into()) } - pub(super) fn cast_from_scalar( + fn cast_from_int_like( &self, v: u128, // raw bits (there is no ScalarTy so we separate data+layout) src_layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 16870489176d7..fb4fe41bdbc4c 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -681,18 +681,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?; assert_eq!(tag_layout.size, tag_val.layout.size); assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed()); - let tag_val = tag_val.to_scalar()?; - trace!("tag value: {:?}", tag_val); + trace!("tag value: {}", tag_val); // Figure out which discriminant and variant this corresponds to. Ok(match *tag_encoding { TagEncoding::Direct => { + // Generate a specific error if `tag_val` is not an integer. + // (`tag_bits` itself is only used for error messages below.) let tag_bits = tag_val + .to_scalar()? .try_to_int() .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? .assert_bits(tag_layout.size); // Cast bits from tag layout to discriminant layout. - let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); + // After the checks we did above, this cannot fail. + let discr_val = + self.misc_cast(&tag_val, discr_layout.ty).unwrap().to_scalar().unwrap(); let discr_bits = discr_val.assert_bits(discr_layout.size); // Convert discriminant to variant index, and catch invalid discriminants. let index = match *op.layout.ty.kind() { @@ -712,6 +716,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (discr_val, index.0) } TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + let tag_val = tag_val.to_scalar()?; // Compute the variant this niche value/"tag" corresponds to. With niche layout, // discriminant (encoded in niche/tag) and variant index are the same. let variants_start = niche_variants.start().as_u32(); From 890a44f66b355d40a284349a22ac82aea82f0520 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Mar 2022 15:56:29 -0800 Subject: [PATCH 4/4] Fix rustdoc for GATs with with anonymous bound regions --- src/librustdoc/clean/mod.rs | 17 +------ src/librustdoc/clean/utils.rs | 45 ++++++++++--------- .../generic-associated-types/issue-94683.rs | 13 ++++++ 3 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 src/test/rustdoc/generic-associated-types/issue-94683.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0d1482ce47017..eba31a17cf4c3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -402,16 +402,7 @@ fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) PathSegment { name: item.name, args: GenericArgs::AngleBracketed { - args: ty.substs[generics.parent_count..] - .iter() - .map(|ty| match ty.unpack() { - ty::subst::GenericArgKind::Lifetime(lt) => { - GenericArg::Lifetime(lt.clean(cx).unwrap()) - } - ty::subst::GenericArgKind::Type(ty) => GenericArg::Type(ty.clean(cx)), - ty::subst::GenericArgKind::Const(c) => GenericArg::Const(Box::new(c.clean(cx))), - }) - .collect(), + args: substs_to_args(cx, &ty.substs[generics.parent_count..], false), bindings: Default::default(), }, } @@ -1379,11 +1370,7 @@ fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_> }); if let Some(lt) = lifetime.cloned() { let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); - let cleaned = if !lt.is_elided() { - lt.clean(cx) - } else { - self::types::Lifetime::elided() - }; + let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() }; substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned)); } indices.lifetimes += 1; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 20eea32560b27..7861b915e9627 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -77,16 +77,12 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { Crate { module, primitives, external_traits: cx.external_traits.clone() } } -fn external_generic_args( +crate fn substs_to_args( cx: &mut DocContext<'_>, - did: DefId, - has_self: bool, - bindings: Vec, - substs: SubstsRef<'_>, -) -> GenericArgs { - let mut skip_self = has_self; - let mut ty_kind = None; - let args: Vec<_> = substs + substs: &[ty::subst::GenericArg<'_>], + mut skip_first: bool, +) -> Vec { + substs .iter() .filter_map(|kind| match kind.unpack() { GenericArgKind::Lifetime(lt) => match *lt { @@ -95,23 +91,32 @@ fn external_generic_args( } _ => lt.clean(cx).map(GenericArg::Lifetime), }, - GenericArgKind::Type(_) if skip_self => { - skip_self = false; + GenericArgKind::Type(_) if skip_first => { + skip_first = false; None } - GenericArgKind::Type(ty) => { - ty_kind = Some(ty.kind()); - Some(GenericArg::Type(ty.clean(cx))) - } + GenericArgKind::Type(ty) => Some(GenericArg::Type(ty.clean(cx))), GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))), }) - .collect(); + .collect() +} + +fn external_generic_args( + cx: &mut DocContext<'_>, + did: DefId, + has_self: bool, + bindings: Vec, + substs: SubstsRef<'_>, +) -> GenericArgs { + let args = substs_to_args(cx, &substs, has_self); if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { - let inputs = match ty_kind.unwrap() { - ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(), - _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() }, - }; + let inputs = + // The trait's first substitution is the one after self, if there is one. + match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() { + ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(), + _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() }, + }; let output = None; // FIXME(#20299) return type comes from a projection now // match types[1].kind { diff --git a/src/test/rustdoc/generic-associated-types/issue-94683.rs b/src/test/rustdoc/generic-associated-types/issue-94683.rs new file mode 100644 index 0000000000000..38ecf5283108f --- /dev/null +++ b/src/test/rustdoc/generic-associated-types/issue-94683.rs @@ -0,0 +1,13 @@ +#![crate_name = "foo"] +#![feature(generic_associated_types)] + +pub trait Trait { + type Gat<'a>; +} + +// Make sure that the elided lifetime shows up + +// @has foo/type.T.html +// @has - "pub type T = " +// @has - "<'_>" +pub type T = fn(&<() as Trait>::Gat<'_>);