mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Rollup merge of #107789 - jieyouxu:issue-107745, r=lcnr
Avoid exposing type parameters and implementation details sourced from macro expansions Fixes #107745. ~~I would like to **request some guidance** for this issue, because I don't think this is a good fix (a band-aid at best).~~ ### The Problem The code ```rust fn main() { println!("{:?}", []); } ``` gets desugared into (`rustc +nightly --edition=2018 issue-107745.rs -Z unpretty=hir`): ```rust #[prelude_import] use std::prelude::rust_2018::*; #[macro_use] extern crate std; fn main() { { ::std::io::_print(<#[lang = "format_arguments"]>::new_v1(&["", "\n"], &[<#[lang = "format_argument"]>::new_debug(&[])])); }; } ``` so the diagnostics code tries to be as specific and helpful as possible, and I think it finds that `[]` needs a type parameter and so does `new_debug`. But since `[]` doesn't have an origin for the type parameter definition, it points to `new_debug` instead and leaks the internal implementation detail since all `[]` has is an type inference variable. ### ~~The Bad Fix~~ ~~This PR currently tries to fix the problem by bypassing the generated function `<#[lang = "format_argument"]>::new_debug` to avoid its generic parameter (I think it is auto-generated from the argument `[_; 0]`?) from getting collected as an `InsertableGenericArg`. This is problematic because it also prevents the help from getting displayed.~~ ~~I think this fix is not ideal and hard-codes the format generated code pattern, but I can't think of a better fix. I have tried asking on Zulip but no responses there yet.~~
This commit is contained in:
commit
dc7559b599
@ -158,8 +158,12 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
|
||||
if infcx.probe_ty_var(ty_vid).is_ok() {
|
||||
warn!("resolved ty var in error message");
|
||||
}
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) =
|
||||
infcx.inner.borrow_mut().type_variables().var_origin(ty_vid).kind
|
||||
|
||||
let mut infcx_inner = infcx.inner.borrow_mut();
|
||||
let ty_vars = infcx_inner.type_variables();
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind
|
||||
&& !var_origin.span.from_expansion()
|
||||
{
|
||||
Some(name)
|
||||
} else {
|
||||
@ -254,7 +258,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
|
||||
var_origin.kind
|
||||
{
|
||||
if name != kw::SelfUpper {
|
||||
if name != kw::SelfUpper && !var_origin.span.from_expansion() {
|
||||
return InferenceDiagnosticsData {
|
||||
name: name.to_string(),
|
||||
span: Some(var_origin.span),
|
||||
@ -780,7 +784,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
// The sources are listed in order of preference here.
|
||||
let tcx = self.infcx.tcx;
|
||||
let ctx = CostCtxt { tcx };
|
||||
let base_cost = match source.kind {
|
||||
match source.kind {
|
||||
InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
|
||||
InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
|
||||
InferSourceKind::GenericArg { def_id, generic_args, .. } => {
|
||||
@ -797,17 +801,17 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
|
||||
30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
|
||||
}
|
||||
};
|
||||
|
||||
let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 };
|
||||
|
||||
base_cost + suggestion_may_apply
|
||||
}
|
||||
}
|
||||
|
||||
/// Uses `fn source_cost` to determine whether this inference source is preferable to
|
||||
/// previous sources. We generally prefer earlier sources.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
|
||||
if new_source.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
let cost = self.source_cost(&new_source) + self.attempt;
|
||||
debug!(?cost);
|
||||
self.attempt += 1;
|
||||
@ -819,6 +823,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
// `let x: _ = iter.collect();`, as this is a very common case.
|
||||
*def_id = Some(did);
|
||||
}
|
||||
|
||||
if cost < self.infer_source_cost {
|
||||
self.infer_source_cost = cost;
|
||||
self.infer_source = Some(new_source);
|
||||
|
@ -0,0 +1,19 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Regression test for #107745.
|
||||
// Previously need_type_info::update_infer_source will consider expressions originating from
|
||||
// macro expressions as candiate "previous sources". This unfortunately can mean that
|
||||
// for macros expansions such as `format!()` internal implementation details can leak, such as:
|
||||
//
|
||||
// ```
|
||||
// error[E0282]: type annotations needed
|
||||
// --> src/main.rs:2:22
|
||||
// |
|
||||
//2 | println!("{:?}", []);
|
||||
// | ^^ cannot infer type of the type parameter `T` declared on the associated function `new_debug`
|
||||
// ```
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", []);
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-107745-avoid-expr-from-macro-expansion.rs:17:22
|
||||
|
|
||||
LL | println!("{:?}", []);
|
||||
| ^^ cannot infer type
|
||||
|
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
@ -1,10 +1,8 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-16966.rs:2:5
|
||||
--> $DIR/issue-16966.rs:2:12
|
||||
|
|
||||
LL | panic!(std::default::Default::default());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
|
||||
|
|
||||
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -17,7 +17,7 @@ fn test2<T1, T2>(arg1 : T1, arg2 : T2) {
|
||||
fn test3<'a>(arg : &'a u32) {
|
||||
let v : Vec<'a = vec![];
|
||||
//~^ ERROR: expected one of
|
||||
//~| ERROR: type annotations needed for `Vec<T>`
|
||||
//~| ERROR: type annotations needed for `Vec<_>`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -39,26 +39,26 @@ help: you might have meant to end the type parameters here
|
||||
LL | let v : Vec<'a> = vec![];
|
||||
| +
|
||||
|
||||
error[E0282]: type annotations needed for `Vec<T>`
|
||||
error[E0282]: type annotations needed for `Vec<_>`
|
||||
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7
|
||||
|
|
||||
LL | let v : Vec<(u32,_) = vec![];
|
||||
| ^
|
||||
|
|
||||
help: consider giving `v` an explicit type, where the type for type parameter `T` is specified
|
||||
help: consider giving `v` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let v: Vec<T> : Vec<(u32,_) = vec![];
|
||||
LL | let v: Vec<_> : Vec<(u32,_) = vec![];
|
||||
| ++++++++
|
||||
|
||||
error[E0282]: type annotations needed for `Vec<T>`
|
||||
error[E0282]: type annotations needed for `Vec<_>`
|
||||
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7
|
||||
|
|
||||
LL | let v : Vec<'a = vec![];
|
||||
| ^
|
||||
|
|
||||
help: consider giving `v` an explicit type, where the type for type parameter `T` is specified
|
||||
help: consider giving `v` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let v: Vec<T> : Vec<'a = vec![];
|
||||
LL | let v: Vec<_> : Vec<'a = vec![];
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0282]: type annotations needed for `Vec<T>`
|
||||
error[E0282]: type annotations needed for `Vec<_>`
|
||||
--> $DIR/cannot_infer_local_or_vec.rs:2:9
|
||||
|
|
||||
LL | let x = vec![];
|
||||
| ^
|
||||
|
|
||||
help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
|
||||
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let x: Vec<T> = vec![];
|
||||
LL | let x: Vec<_> = vec![];
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0282]: type annotations needed for `(Vec<T>,)`
|
||||
error[E0282]: type annotations needed for `(Vec<_>,)`
|
||||
--> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9
|
||||
|
|
||||
LL | let (x, ) = (vec![], );
|
||||
| ^^^^^ ---------- type must be known at this point
|
||||
|
|
||||
help: consider giving this pattern a type, where the type for type parameter `T` is specified
|
||||
help: consider giving this pattern a type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let (x, ): (Vec<T>,) = (vec![], );
|
||||
LL | let (x, ): (Vec<_>,) = (vec![], );
|
||||
| +++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user