From 9f7cc5faa0e9c9b865a95aa1fb0725528b95595e Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sun, 2 Oct 2016 12:59:44 -0700 Subject: [PATCH 1/4] Use a distinct error code for "if may be missing an else clause" Introduce the possibility of assigning distinct error codes to the various origin types of E0308. Start by assigning E0317 for the "IfExpressionWithNoElse" case, and write a long diagnostic specific to this case. Fixes #36596 --- src/librustc/diagnostics.rs | 15 +++++++++++++++ src/librustc/infer/error_reporting.rs | 8 ++++---- src/librustc/infer/mod.rs | 19 +++++++++++++++++++ .../compile-fail/if-without-else-result.rs | 2 +- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index de68cc707ad7a..f43cbb2696df3 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1431,6 +1431,21 @@ fn make_child<'elve>(x: &mut &'elve isize, y: &mut &'elve isize) { ``` "##, +E0317: r##" +An `if` expression without an `else` block is required to have the type `()`. +This error occurs when the `if` block has a type other than `()`. For example: + +```compile_fail,E0317 +fn main() { + let x = 5; + let a = if x == 5 { 1 }; +} +``` + +To resolve this error, either add an `else` block having the same type as the +`if` block, or adjust the `if` block so that it has the type `()`. +"##, + E0398: r##" In Rust 1.3, the default object lifetime bounds are expected to change, as described in RFC #1156 [1]. You are getting a warning because the compiler diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 3f216d6916851..f157b02f14d55 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -577,10 +577,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { terr: &TypeError<'tcx>) -> DiagnosticBuilder<'tcx> { - // FIXME: do we want to use a different error code for each origin? - let mut diag = struct_span_err!( - self.tcx.sess, trace.origin.span(), E0308, - "{}", trace.origin.as_failure_str() + let mut diag = self.tcx.sess.struct_span_err_with_code( + trace.origin.span(), + trace.origin.as_failure_str(), + trace.origin.as_error_code() ); self.note_type_err(&mut diag, trace.origin, None, Some(trace.values), terr); diag diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 39fc50666a8ce..036b3ae62846b 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -219,6 +219,25 @@ pub enum TypeOrigin { } impl TypeOrigin { + fn as_error_code(&self) -> &'static str { + match self { + // FIXME: use distinct codes for each case + &TypeOrigin::Misc(_) => "E0308", + &TypeOrigin::RelateOutputImplTypes(_) => "E0308", + &TypeOrigin::ExprAssignable(_) => "E0308", + &TypeOrigin::MethodCompatCheck(_) => "E0308", + &TypeOrigin::MatchExpressionArm(..) => "E0308", + &TypeOrigin::IfExpression(_) => "E0308", + &TypeOrigin::IfExpressionWithNoElse(_) => "E0317", + &TypeOrigin::RangeExpression(_) => "E0308", + &TypeOrigin::EquatePredicate(_) => "E0308", + &TypeOrigin::MainFunctionType(_) => "E0308", + &TypeOrigin::StartFunctionType(_) => "E0308", + &TypeOrigin::IntrinsicType(_) => "E0308", + &TypeOrigin::MethodReceiver(_) => "E0308", + } + } + fn as_failure_str(&self) -> &'static str { match self { &TypeOrigin::Misc(_) | diff --git a/src/test/compile-fail/if-without-else-result.rs b/src/test/compile-fail/if-without-else-result.rs index e8aa1f70ea1dc..95bcce5a8474a 100644 --- a/src/test/compile-fail/if-without-else-result.rs +++ b/src/test/compile-fail/if-without-else-result.rs @@ -10,7 +10,7 @@ fn main() { let a = if true { true }; - //~^ ERROR if may be missing an else clause + //~^ ERROR if may be missing an else clause [E0317] //~| expected type `()` //~| found type `bool` //~| expected (), found bool From 71f9e2e4d2dfe781237fd1a5754e82055a11594c Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 3 Oct 2016 09:28:46 -0700 Subject: [PATCH 2/4] Continue to use struct_span_err! macro --- src/librustc/infer/error_reporting.rs | 16 +++++++++++----- src/librustc/infer/mod.rs | 19 ------------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index f157b02f14d55..7a969af3d6a92 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -577,11 +577,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { terr: &TypeError<'tcx>) -> DiagnosticBuilder<'tcx> { - let mut diag = self.tcx.sess.struct_span_err_with_code( - trace.origin.span(), - trace.origin.as_failure_str(), - trace.origin.as_error_code() - ); + let span = trace.origin.span(); + let failure_str = trace.origin.as_failure_str(); + let mut diag = match trace.origin { + // FIXME: use distinct codes for each case + TypeOrigin::IfExpressionWithNoElse(_) => { + struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) + }, + _ => { + struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str) + }, + }; self.note_type_err(&mut diag, trace.origin, None, Some(trace.values), terr); diag } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 036b3ae62846b..39fc50666a8ce 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -219,25 +219,6 @@ pub enum TypeOrigin { } impl TypeOrigin { - fn as_error_code(&self) -> &'static str { - match self { - // FIXME: use distinct codes for each case - &TypeOrigin::Misc(_) => "E0308", - &TypeOrigin::RelateOutputImplTypes(_) => "E0308", - &TypeOrigin::ExprAssignable(_) => "E0308", - &TypeOrigin::MethodCompatCheck(_) => "E0308", - &TypeOrigin::MatchExpressionArm(..) => "E0308", - &TypeOrigin::IfExpression(_) => "E0308", - &TypeOrigin::IfExpressionWithNoElse(_) => "E0317", - &TypeOrigin::RangeExpression(_) => "E0308", - &TypeOrigin::EquatePredicate(_) => "E0308", - &TypeOrigin::MainFunctionType(_) => "E0308", - &TypeOrigin::StartFunctionType(_) => "E0308", - &TypeOrigin::IntrinsicType(_) => "E0308", - &TypeOrigin::MethodReceiver(_) => "E0308", - } - } - fn as_failure_str(&self) -> &'static str { match self { &TypeOrigin::Misc(_) | From 080ee041e4372a4dec0848e8838bfd2ab019a629 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 3 Oct 2016 09:49:17 -0700 Subject: [PATCH 3/4] Revise long diagnostic --- src/librustc/diagnostics.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index f43cbb2696df3..142f8f5c719c2 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1432,8 +1432,9 @@ fn make_child<'elve>(x: &mut &'elve isize, y: &mut &'elve isize) { "##, E0317: r##" -An `if` expression without an `else` block is required to have the type `()`. -This error occurs when the `if` block has a type other than `()`. For example: +This error occurs when an `if` expression without an `else` block is used in a +context where a type other than `()` is expected, for example a `let` +expression: ```compile_fail,E0317 fn main() { @@ -1442,8 +1443,9 @@ fn main() { } ``` -To resolve this error, either add an `else` block having the same type as the -`if` block, or adjust the `if` block so that it has the type `()`. +An `if` expression without an `else` block has the type `()`, so this is a type +error. To resolve it, add an `else` block having the same type as the `if` +block. "##, E0398: r##" From d07602b573d210775dd183d414c1ac36a2751144 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 15 Oct 2016 08:49:16 -0700 Subject: [PATCH 4/4] Remove FIXME --- src/librustc/infer/error_reporting.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 7a969af3d6a92..373ea4aac57b0 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -580,7 +580,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let span = trace.origin.span(); let failure_str = trace.origin.as_failure_str(); let mut diag = match trace.origin { - // FIXME: use distinct codes for each case TypeOrigin::IfExpressionWithNoElse(_) => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) },