Rollup merge of #122768 - oli-obk:why_is_E0699_so_bad, r=WaffleLapkin
Use the more informative generic type inference failure error on method calls on raw pointers
This commit is contained in:
commit
643dee7573
@ -1,8 +1,10 @@
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
A method was called on a raw pointer whose inner type wasn't completely known.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,edition2018,E0699
|
||||
```compile_fail,edition2018
|
||||
# #![deny(warnings)]
|
||||
# fn main() {
|
||||
let foo = &1;
|
||||
|
@ -441,7 +441,7 @@ E0695: 0695,
|
||||
E0696: 0696,
|
||||
E0697: 0697,
|
||||
E0698: 0698,
|
||||
E0699: 0699,
|
||||
E0699: 0699, // REMOVED: merged into generic inference var error
|
||||
E0700: 0700,
|
||||
E0701: 0701,
|
||||
E0703: 0703,
|
||||
|
@ -93,9 +93,6 @@ hir_typeck_lossy_provenance_ptr2int =
|
||||
.suggestion = use `.addr()` to obtain the address of a pointer
|
||||
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
|
||||
|
||||
hir_typeck_method_call_on_unknown_raw_pointee =
|
||||
cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
||||
hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
|
||||
|
||||
hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
|
||||
|
@ -76,13 +76,6 @@ pub struct StructExprNonExhaustive {
|
||||
pub what: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = E0699)]
|
||||
pub struct MethodCallOnUnknownRawPointee {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)]
|
||||
pub struct FunctionalRecordUpdateOnNonStruct {
|
||||
|
@ -3,7 +3,6 @@ use super::CandidateSource;
|
||||
use super::MethodError;
|
||||
use super::NoMatchData;
|
||||
|
||||
use crate::errors::MethodCallOnUnknownRawPointee;
|
||||
use crate::FnCtxt;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
@ -430,21 +429,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if is_suggestion.0 {
|
||||
// Ambiguity was encountered during a suggestion. Just keep going.
|
||||
debug!("ProbeContext: encountered ambiguity in suggestion");
|
||||
} else if bad_ty.reached_raw_pointer && !self.tcx.features().arbitrary_self_types {
|
||||
} else if bad_ty.reached_raw_pointer
|
||||
&& !self.tcx.features().arbitrary_self_types
|
||||
&& !self.tcx.sess.at_least_rust_2018()
|
||||
{
|
||||
// this case used to be allowed by the compiler,
|
||||
// so we do a future-compat lint here for the 2015 edition
|
||||
// (see https://github.com/rust-lang/rust/issues/46906)
|
||||
if self.tcx.sess.at_least_rust_2018() {
|
||||
self.dcx().emit_err(MethodCallOnUnknownRawPointee { span });
|
||||
} else {
|
||||
self.tcx.node_span_lint(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
"type annotations needed",
|
||||
|_| {},
|
||||
);
|
||||
}
|
||||
self.tcx.node_span_lint(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
"type annotations needed",
|
||||
|_| {},
|
||||
);
|
||||
} else {
|
||||
// Ended up encountering a type variable when doing autoderef,
|
||||
// but it may not be a type variable after processing obligations
|
||||
@ -455,10 +453,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
|
||||
let ty = self.resolve_vars_if_possible(ty.value);
|
||||
let guar = match *ty.kind() {
|
||||
ty::Infer(ty::TyVar(_)) => self
|
||||
.err_ctxt()
|
||||
.emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true)
|
||||
.emit(),
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
let raw_ptr_call =
|
||||
bad_ty.reached_raw_pointer && !self.tcx.features().arbitrary_self_types;
|
||||
let mut err = self.err_ctxt().emit_inference_failure_err(
|
||||
self.body_id,
|
||||
span,
|
||||
ty.into(),
|
||||
E0282,
|
||||
!raw_ptr_call,
|
||||
);
|
||||
if raw_ptr_call {
|
||||
err.span_label(span, "cannot call a method on a raw pointer with an unknown pointee type");
|
||||
}
|
||||
err.emit()
|
||||
}
|
||||
ty::Error(guar) => guar,
|
||||
_ => bug!("unexpected bad final type in method autoderef"),
|
||||
};
|
||||
|
@ -71,10 +71,12 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
|
||||
let path = root_path.join(Path::new(ERROR_CODES_PATH));
|
||||
let file =
|
||||
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
|
||||
let path = path.display();
|
||||
|
||||
let mut error_codes = Vec::new();
|
||||
|
||||
for line in file.lines() {
|
||||
for (line_index, line) in file.lines().enumerate() {
|
||||
let line_index = line_index + 1;
|
||||
let line = line.trim();
|
||||
|
||||
if line.starts_with('E') {
|
||||
@ -82,39 +84,54 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
|
||||
|
||||
// Extract the error code from the line. Emit a fatal error if it is not in the correct
|
||||
// format.
|
||||
let err_code = if let Some(err_code) = split_line {
|
||||
err_code.0.to_owned()
|
||||
} else {
|
||||
let Some(split_line) = split_line else {
|
||||
errors.push(format!(
|
||||
"Expected a line with the format `Eabcd: abcd, \
|
||||
"{path}:{line_index}: Expected a line with the format `Eabcd: abcd, \
|
||||
but got \"{}\" without a `:` delimiter",
|
||||
line,
|
||||
));
|
||||
continue;
|
||||
};
|
||||
|
||||
let err_code = split_line.0.to_owned();
|
||||
|
||||
// If this is a duplicate of another error code, emit a fatal error.
|
||||
if error_codes.contains(&err_code) {
|
||||
errors.push(format!("Found duplicate error code: `{}`", err_code));
|
||||
errors.push(format!(
|
||||
"{path}:{line_index}: Found duplicate error code: `{}`",
|
||||
err_code
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut chars = err_code.chars();
|
||||
chars.next();
|
||||
assert_eq!(chars.next(), Some('E'));
|
||||
let error_num_as_str = chars.as_str();
|
||||
|
||||
// Ensure that the line references the correct markdown file.
|
||||
let expected_filename = format!(" {},", error_num_as_str);
|
||||
if expected_filename != split_line.unwrap().1 {
|
||||
let rest = split_line.1.split_once(',');
|
||||
let Some(rest) = rest else {
|
||||
errors.push(format!(
|
||||
"`{}:` should be followed by `{}` but instead found `{}` in \
|
||||
"{path}:{line_index}: Expected a line with the format `Eabcd: abcd, \
|
||||
but got \"{}\" without a `,` delimiter",
|
||||
line,
|
||||
));
|
||||
continue;
|
||||
};
|
||||
if error_num_as_str != rest.0.trim() {
|
||||
errors.push(format!(
|
||||
"{path}:{line_index}: `{}:` should be followed by `{},` but instead found `{}` in \
|
||||
`compiler/rustc_error_codes/src/lib.rs`",
|
||||
err_code,
|
||||
expected_filename,
|
||||
split_line.unwrap().1,
|
||||
error_num_as_str,
|
||||
split_line.1,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
if !rest.1.trim().is_empty() && !rest.1.trim().starts_with("//") {
|
||||
errors.push(format!("{path}:{line_index}: should only have one error per line"));
|
||||
continue;
|
||||
}
|
||||
|
||||
error_codes.push(err_code);
|
||||
}
|
||||
@ -146,14 +163,14 @@ fn check_error_codes_docs(
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that the file is referenced in `error_codes.rs`
|
||||
// Make sure that the file is referenced in `rustc_error_codes/src/lib.rs`
|
||||
let filename = path.file_name().unwrap().to_str().unwrap().split_once('.');
|
||||
let err_code = filename.unwrap().0; // `unwrap` is ok because we know the filename is in the correct format.
|
||||
|
||||
if error_codes.iter().all(|e| e != err_code) {
|
||||
errors.push(format!(
|
||||
"Found valid file `{}` in error code docs directory without corresponding \
|
||||
entry in `error_code.rs`",
|
||||
entry in `rustc_error_codes/src/lib.rs`",
|
||||
path.display()
|
||||
));
|
||||
return;
|
||||
|
@ -6,6 +6,6 @@
|
||||
fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
//~^ error: type annotations needed
|
||||
let _ = y.is_null();
|
||||
//~^ error: cannot call a method on a raw pointer with an unknown pointee type [E0699]
|
||||
}
|
||||
|
@ -1,9 +1,17 @@
|
||||
error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
|
||||
--> $DIR/edition-raw-pointer-method-2018.rs:9:15
|
||||
error[E0282]: type annotations needed for `*const _`
|
||||
--> $DIR/edition-raw-pointer-method-2018.rs:8:9
|
||||
|
|
||||
LL | let y = &x as *const _;
|
||||
| ^
|
||||
LL |
|
||||
LL | let _ = y.is_null();
|
||||
| ^^^^^^^
|
||||
| ------- cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
|
||||
help: consider giving `y` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let y: *const _ = &x as *const _;
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0699`.
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
@ -8,10 +8,10 @@ fn main() {
|
||||
let ptr = &val as *const u32;
|
||||
unsafe {
|
||||
let _a: i32 = (ptr as *const _).read();
|
||||
//~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
|
||||
//~^ ERROR type annotations needed
|
||||
let b = ptr as *const _;
|
||||
//~^ ERROR type annotations needed
|
||||
let _b: u8 = b.read();
|
||||
//~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
|
||||
let _c = (ptr as *const u8).read(); // we know the type here
|
||||
}
|
||||
|
||||
@ -19,10 +19,10 @@ fn main() {
|
||||
let ptr = &mut val as *mut u32;
|
||||
unsafe {
|
||||
let _a: i32 = (ptr as *mut _).read();
|
||||
//~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
|
||||
//~^ ERROR type annotations needed
|
||||
let b = ptr as *mut _;
|
||||
//~^ ERROR type annotations needed
|
||||
b.write(10);
|
||||
//~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
|
||||
(ptr as *mut i32).write(1000); // we know the type here
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,49 @@
|
||||
error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/call_method_unknown_pointee.rs:10:41
|
||||
|
|
||||
LL | let _a: i32 = (ptr as *const _).read();
|
||||
| ^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
||||
error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
|
||||
--> $DIR/call_method_unknown_pointee.rs:13:24
|
||||
error[E0282]: type annotations needed for `*const _`
|
||||
--> $DIR/call_method_unknown_pointee.rs:12:13
|
||||
|
|
||||
LL | let b = ptr as *const _;
|
||||
| ^
|
||||
LL |
|
||||
LL | let _b: u8 = b.read();
|
||||
| ^^^^
|
||||
| ---- cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
|
||||
help: consider giving `b` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let b: *const _ = ptr as *const _;
|
||||
| ++++++++++
|
||||
|
||||
error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/call_method_unknown_pointee.rs:21:39
|
||||
|
|
||||
LL | let _a: i32 = (ptr as *mut _).read();
|
||||
| ^^^^
|
||||
| |
|
||||
| cannot infer type
|
||||
| cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
||||
error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
|
||||
--> $DIR/call_method_unknown_pointee.rs:24:11
|
||||
error[E0282]: type annotations needed for `*mut _`
|
||||
--> $DIR/call_method_unknown_pointee.rs:23:13
|
||||
|
|
||||
LL | let b = ptr as *mut _;
|
||||
| ^
|
||||
LL |
|
||||
LL | b.write(10);
|
||||
| ^^^^^
|
||||
| ----- cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
|
||||
help: consider giving `b` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let b: *mut _ = ptr as *mut _;
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0699`.
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user