From 45fd29621dc0827c12f4534976026f1f8d1676b5 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 7 Jul 2015 18:45:52 +0300 Subject: [PATCH] mark user-defined derefs as non-constant Fixes #25901 --- src/librustc/diagnostics.rs | 3 ++- src/librustc/middle/check_const.rs | 20 ++++++++++++++++++++ src/test/compile-fail/issue-25901.rs | 23 +++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-25901.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index eb504d03209f6..c329f2fb012db 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1237,5 +1237,6 @@ register_diagnostics! { E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime E0316, // nested quantification of lifetimes - E0370 // discriminant overflow + E0370, // discriminant overflow + E0400 // overloaded derefs are not allowed in constants } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index b5c78340d022d..59f91a50f7421 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -405,6 +405,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { let node_ty = self.tcx.node_id_to_type(ex.id); check_expr(self, ex, node_ty); + check_adjustments(self, ex); // Special-case some expressions to avoid certain flags bubbling up. match ex.node { @@ -777,6 +778,25 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } +/// Check the adjustments of an expression +fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &ast::Expr) { + match v.tcx.tables.borrow().adjustments.get(&e.id) { + None | Some(&ty::AdjustReifyFnPointer) | Some(&ty::AdjustUnsafeFnPointer) => {} + Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs, .. })) => { + if (0..autoderefs as u32).any(|autoderef| { + v.tcx.is_overloaded_autoderef(e.id, autoderef) + }) { + v.add_qualif(ConstQualif::NOT_CONST); + if v.mode != Mode::Var { + span_err!(v.tcx.sess, e.span, E0400, + "user-defined dereference operators are not allowed in {}s", + v.msg()); + } + } + } + } +} + pub fn check_crate(tcx: &ty::ctxt) { visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, diff --git a/src/test/compile-fail/issue-25901.rs b/src/test/compile-fail/issue-25901.rs new file mode 100644 index 0000000000000..3254f0b2aa9bd --- /dev/null +++ b/src/test/compile-fail/issue-25901.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct A; +struct B; + +static S: &'static B = &A; //~ ERROR user-defined dereference operators + +use std::ops::Deref; + +impl Deref for A { + type Target = B; + fn deref(&self)->&B { static B_: B = B; &B_ } +} + +fn main(){}