Issue 1:
Hi,

I was trying to use the LLVM C bindings from Rust, but I ran into a mysterious error when I tried to use LLVMGetTypeKind. The Rust program is like this:

#[allow(cstack)];
use std::libc::{c_uint};

pub enum Context_opaque {}
pub type ContextPtr = *Context_opaque;
pub enum Type_opaque {}
pub type TypePtr = *Type_opaque;

#[repr(C)]
pub enum LLVMTypeKind {
LLVMVoidTypeKind,
LLVMHalfTypeKind,
LLVMFloatTypeKind,
LLVMDoubleTypeKind,
LLVMX86_FP80TypeKind,
LLVMFP128TypeKind,
LLVMPPC_FP128TypeKind,
LLVMLabelTypeKind,
LLVMIntegerTypeKind,
LLVMFunctionTypeKind,
LLVMStructTypeKind,
LLVMArrayTypeKind,
LLVMPointerTypeKind,
LLVMVectorTypeKind,
LLVMMetadataTypeKind,
LLVMX86_MMXTypeKind
}

#[link_args = "-lLLVMCore -lLLVMSupport"]
extern {
pub fn LLVMContextCreate() -> ContextPtr;
pub fn LLVMContextDispose(c: ContextPtr);
pub fn LLVMGetTypeKind(t: TypePtr) -> LLVMTypeKind;
pub fn LLVMIntTypeInContext(c: ContextPtr, bits: c_uint) -> TypePtr;
}

fn main() {
unsafe {
let ctx_ptr = LLVMContextCreate();
let int32_ptr = LLVMIntTypeInContext(ctx_ptr, 32);
let kind = LLVMGetTypeKind(int32_ptr); // boom!
println!("{}", kind as uint);
LLVMContextDispose(ctx_ptr);
}
}

When compiled and executed, LLVM crashes with

Unhandled TypeID.
UNREACHABLE executed at Core.cpp:164!
Aborted (core dumped)

After some investigation, I made rustc emit LLVM bitcode and found something strange:

declare void @LLVMGetTypeKind(%enum.LLVMTypeKind* sret, %enum.Type_opaque*) unnamed_addr

call void @LLVMGetTypeKind(%enum.LLVMTypeKind* sret %kind, %enum.Type_opaque* %11)

rustc declared the LLVMGetTypeKind function with wrong parameters, so the function, when called, got a pointer to unitialized value on stack instead of a ContextRef.

I tried to declare LLVMGetTypeKind as a function returning c_uint and everything worked well (it is probably the reason why rustc's LLVM bindings declare LLVMTypeKind as a series of static variables).

Is this a bug or a feature? If it is a feature, it is worth documenting! :)

Issue 2:
First off, the operator precedence of a..b is extremely low.

struct Range recently got #[derive(Eq)], so people might want to compare a range to an expression in range notation.

r == 1..10 parses as (r == 1)..10. Similarly, 1..10 == r parses as 1..(10 == r). Both result in type errors.

I think there's no good reason for .. to have a precedence lower than comparisons. I'd suggest to put it in-between the comparison operators and the bitwise operators.

But the current implementation gets weirder when we consider the other forms of range notation:

r == 1.. parses as (r == 1).., and is a type error (or maybe a RangeFrom<bool>).

But r == ..1 parses as r == (..1), and is a valid range comparison.

In the other direction, ..1 == r parses as ..(1 == r) and is potentially a RangeTo<bool>.

But 1.. == r is a syntax error (expected one of ) or ,, found ==).

This inconsistent with the prefix form.

If we keep the current precedence of .. (lower than all binops), I think we should disallow r == ..1. I think this can be implemented easily by using RESTRICTION_NO_DOTS when parsing the RHS of any binop.

Also, we should use RESTRICTION_NO_DOTS when parsing the RHS of prefix-version ..expr -- currently ..1..2 is a RangeTo<Range<_>>, while 1..2..3 and 1..2.. both are syntax errors.

If we increase the precedence, we will need to be careful not to allow code like 1 + ..2. I think any binop with precedence smaller than that of .. will have to use RESTRICTION_NO_DOTS on the RHS.

I also think the implementation can be simplified quite a bit if the prefix .. wasn't handled in parse_prefix_expr (as that's only supposed to be used for operators with high precedence), but at the same level as the binary and postfix version (parse_assign_expr, or parse_binops if we change the precedence). This would allow us to get rid of RESTRICTION_NO_DOTS and use the normal operator precedence handling instead.