diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index bd9b443fad..36cf739854 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -507,6 +507,7 @@ impl Program<'_> { })?; let mut maybe_decl = None; + let mut ambiguous = false; 'outer: for decl in declarations { if args.len() != decl.parameters.len() { @@ -538,17 +539,22 @@ impl Program<'_> { if exact { maybe_decl = Some(decl); + ambiguous = false; break; } else if maybe_decl.is_some() { - return Err(ErrorKind::SemanticError( - meta, - format!("Ambiguous best function for '{}'", name).into(), - )); + ambiguous = true; } else { maybe_decl = Some(decl) } } + if ambiguous { + return Err(ErrorKind::SemanticError( + meta, + format!("Ambiguous best function for '{}'", name).into(), + )); + } + let decl = maybe_decl.ok_or_else(|| { ErrorKind::SemanticError( meta, diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index 4b1b9ae32a..f555ec2dce 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -463,6 +463,32 @@ fn constants() { assert!(constants.next().is_none()); } +#[test] +fn function_overloading() { + let mut entry_points = crate::FastHashMap::default(); + entry_points.insert("".to_string(), ShaderStage::Vertex); + + parse_program( + r#" + # version 450 + + float saturate(float v) { return clamp(v, 0.0, 1.0); } + vec2 saturate(vec2 v) { return clamp(v, vec2(0.0), vec2(1.0)); } + vec3 saturate(vec3 v) { return clamp(v, vec3(0.0), vec3(1.0)); } + vec4 saturate(vec4 v) { return clamp(v, vec4(0.0), vec4(1.0)); } + + void main() { + float v1 = saturate(1.5); + vec2 v2 = saturate(vec2(0.5, 1.5)); + vec3 v3 = saturate(vec3(0.5, 1.5, 2.5)); + vec3 v4 = saturate(vec4(0.5, 1.5, 2.5, 3.5)); + } + "#, + &entry_points, + ) + .unwrap(); +} + #[test] fn implicit_conversions() { let mut entry_points = crate::FastHashMap::default();