Skip to content

ensure projections are prohibited when type parameters are #28396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,7 @@ register_diagnostics! {
// E0006 // merged with E0005
// E0134,
// E0135,
E0229, // associated type bindings are not allowed here
E0264, // unknown external lang item
E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
Expand Down
40 changes: 22 additions & 18 deletions src/librustc/middle/astconv_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,40 @@

use middle::def;
use middle::ty::{self, Ty};
use rustc_front::hir as ast;

pub const NO_REGIONS: usize = 1;
pub const NO_TPS: usize = 2;
use syntax::codemap::Span;
use rustc_front::hir as ast;

pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: usize) {
pub fn prohibit_type_params(tcx: &ty::ctxt, segments: &[ast::PathSegment]) {
for segment in segments {
if (flags & NO_TPS) != 0 {
for typ in segment.parameters.types() {
span_err!(tcx.sess, typ.span, E0109,
"type parameters are not allowed on this type");
break;
}
for typ in segment.parameters.types() {
span_err!(tcx.sess, typ.span, E0109,
"type parameters are not allowed on this type");
break;
}

if (flags & NO_REGIONS) != 0 {
for lifetime in segment.parameters.lifetimes() {
span_err!(tcx.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type");
break;
}
for lifetime in segment.parameters.lifetimes() {
span_err!(tcx.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type");
break;
}
for binding in segment.parameters.bindings() {
prohibit_projection(tcx, binding.span);
break;
}
}
}

pub fn prohibit_projection(tcx: &ty::ctxt, span: Span)
{
span_err!(tcx.sess, span, E0229,
"associated type bindings are not allowed here");
}

pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
segments: &[ast::PathSegment],
nty: ast::PrimTy)
-> Ty<'tcx> {
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, segments);
match nty {
ast::TyBool => tcx.types.bool,
ast::TyChar => tcx.types.char,
Expand Down
21 changes: 10 additions & 11 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
//! case but `&a` in the second. Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.

use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
use middle::const_eval::{self, ConstVal};
use middle::const_eval::EvalHint::UncheckedExprHint;
use middle::def;
Expand Down Expand Up @@ -1210,7 +1210,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,

debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);

check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, slice::ref_slice(item_segment));

// Find the type of the associated item, and the trait where the associated
// item is declared.
Expand Down Expand Up @@ -1312,7 +1312,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
{
let tcx = this.tcx();

check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, slice::ref_slice(item_segment));

let self_ty = if let Some(ty) = opt_self_ty {
ty
Expand Down Expand Up @@ -1401,7 +1401,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
base_segments.last().unwrap(),
&mut projection_bounds);

check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
trait_ref_to_object_type(this,
rscope,
span,
Expand All @@ -1410,7 +1410,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
&[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
ast_path_to_ty(this,
rscope,
span,
Expand All @@ -1419,12 +1419,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
base_segments.last().unwrap())
}
def::DefTyParam(space, index, _, name) => {
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, base_segments);
tcx.mk_param(space, index, name)
}
def::DefSelfTy(_, Some((_, self_ty_id))) => {
// Self in impl (we know the concrete type).
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, base_segments);
if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
if let Some(free_substs) = this.get_free_substs() {
ty.subst(tcx, free_substs)
Expand All @@ -1437,11 +1437,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
}
def::DefSelfTy(Some(_), None) => {
// Self in trait.
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, base_segments);
tcx.mk_self_type()
}
def::DefAssociatedTy(trait_did, _) => {
check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS);
prohibit_type_params(tcx, &base_segments[..base_segments.len()-2]);
qpath_to_ty(this,
rscope,
span,
Expand Down Expand Up @@ -2191,8 +2191,7 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
bindings: &[ConvertedBinding<'tcx>])
{
for binding in bindings.iter().take(1) {
span_err!(tcx.sess, binding.span, E0229,
"associated type bindings are not allowed here");
prohibit_projection(tcx, binding.span);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use self::TupleArgumentsFlag::*;
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
use check::_match::pat_ctxt;
use fmt_macros::{Parser, Piece, Position};
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
use middle::astconv_util::prohibit_type_params;
use middle::def;
use middle::def_id::{DefId, LOCAL_CRATE};
use middle::infer;
Expand Down Expand Up @@ -4535,8 +4535,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
for (opt_space, segment) in segment_spaces.iter().zip(segments) {
match *opt_space {
None => {
check_path_args(fcx.tcx(), slice::ref_slice(segment),
NO_TPS | NO_REGIONS);
prohibit_type_params(fcx.tcx(), slice::ref_slice(segment));
}

Some(space) => {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3294,7 +3294,6 @@ register_diagnostics! {
E0226, // only a single explicit lifetime bound is permitted
E0227, // ambiguous lifetime bound, explicit lifetime bound required
E0228, // explicit lifetime bound required
E0229, // associated type bindings are not allowed here
E0230, // there is no type parameter on trait
E0231, // only named substitution parameters are allowed
// E0233,
Expand Down
31 changes: 31 additions & 0 deletions src/test/compile-fail/issue-24682.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

trait A: Sized {
type N;
fn x() ->
Self<
N= //~ ERROR associated type bindings are not allowed here
Self::N> {
loop {}
}
fn y(&self) ->
std
<N=()> //~ ERROR associated type bindings are not allowed here
::option::Option<()>
{ None }
fn z(&self) ->
u32<N=()> //~ ERROR associated type bindings are not allowed here
{ 42 }

}

fn main() {
}